Files
ln-bi/docs/mileage-query-performance-2026-10-27.md
shishengliang e2f932232f
ci/woodpecker/push/woodpecker Pipeline was successful
feat(mileage): 接入区间汇总并复用查询结果
2026-10-29 09:11:21 +08:00

5.9 KiB
Raw Permalink Blame History

里程监控查询交互与性能分析(2026-10-27)

当前已完成第三阶段 区间汇总接入与验证,首次查询不再拉取全量逐日明细。

本文保留第一阶段诊断与修改记录。后续已实现 OneOS 查询复用,见 第二阶段实现与验证;可转交上游的独立建议见 OneOS 性能优化反馈。

本次修改

实时监控页将编辑中的筛选条件与已提交条件分开。日期输入、快捷日期、搜索选择、筛选标签清理、重置与排序修改只更新草稿,点击「查询」才提交。首次进入仍加载默认日期;主动刷新与确认后的滚动分页继续保留。移除页面每分钟自动刷新,避免编辑过程中产生后台查询。

高级筛选和全屏均提供查询按钮。草稿未提交时禁用刷新和导出,并暂停加载更多,避免使用未确认条件。日期不完整或起止倒置时不可提交。接口失败显示重试提示;数据统计使用返回结果的日期范围。保留原有权限过滤、数据来源规则及全屏参数差异。

范围:本次修改实时监控页;统计报表、每日汇报和单车详情的日期交互未改动。后端数据缓存、上游分页及实时性策略未修改。

测量方式

在本地开发环境中,使用已有配置调用 queryRangeMileage,仅执行数据读取。临时探针包裹 fetch(统计至 JSON 读取完毕)及数据库 execute,不记录凭据和车辆明细。来源为仪表数据,测量日期均为已结束的上海自然日。

这些是单次样本,不代表 P95 或高并发表现;总耗时为服务端查询函数耗时,包含网络、解析、数据库及合并计算,不包含浏览器渲染。同一进程重复查询可复用已有单日缓存。

区间 总耗时 区间上游记录数 区间分页请求数
10 月 26 日 1,644 ms 1,024 1
10 月 20–26 日,首次 3,100 ms 7,168 2
10 月 20–26 日,重复 2,994 ms 7,168 2
10 月 1–26 日,首次 11,123 ms 26,624 6
10 月 1–26 日,重复 9,510 ms 26,624 6

单日样本同时另发结束日和前一日的两个单日请求,各约 1.6 秒。26 天首次查询的 6 个游标分页分别约 2,283 / 2,114 / 1,775 / 1,762 / 1,682 / 1,466 ms,串行耗时合计约 11.08 秒,几乎占满总耗时。

车辆关联 SQL 返回 765 行,耗时 58–168 ms;考核目标关联 SQL 返回 512 行,耗时 25–125 ms。它们与上游查询并行执行。本次样本不支持把主要瓶颈归因于数据库或浏览器渲染。

原因与代码依据

  1. 每次改条件就发请求。 MonitoringView.tsx 原本直接以全部输入状态构建 monitoringQuery,依赖它的 loadFirstPage 改变后由 Effect 自动调用;另有 60 秒轮询。本次已经改为显式提交。
  2. 页面分页发生在全量查询之后。 src/server/routes/mileage/monitoring.ts 先调用 queryRangeMileage,然后执行权限过滤、业务筛选、排序和 slice。请求第 2 页或只选一辆车仍先执行全量区间查询。
  3. 区间查询没有结果缓存。 src/server/routes/mileage/oneos-api.ts 中的 fetchOneOsMileageDates 只有 rangeInflight,完成后删除;单日查询的历史 6 小时缓存不覆盖此路径。重复查询同一个月仍发 6 次分页请求,与实测吻合。
  4. 游标必须串行。 requestRange 每页 5,000 条,拿到 nextCursor 才能发下一页。不能直接并行发后续页。前端固定传 startDate/endDate,即使只选一天也会走区间接口,再额外取结束日单日数据。
  5. 重试可能进一步拉长等待。 本地配置每次上游调用超时 20 秒,最多尝试 3 次,中间等待 1 秒、2 秒。某一页连续超时即可约 63 秒;这是代码推导,实测样本没有出现超时。接口没有整个区间请求的总时限。
  6. 开发环境首次请求有两次。 src/main.tsx 启用 React StrictMode,浏览器测试观察到首次挂载两次请求;用户点击查询只产生一次请求。上游相同在途请求可合并,但数据库工作仍重复。这与生产环境行为需区分,不能为消除开发重复而移除 StrictMode。

后续优化顺序

  1. 优先让分页、排序、导出复用一次已完成查询的结果。 采用明确的查询快照或按日期范围与数据来源缓存原始结果,再按当前用户权限过滤。需要定义刷新失效方式及允许的数据延迟;不能缓存某个用户过滤后的结果再跨用户共享。这样能去掉重复查询的主要等待,但不会缩短首次上游查询。
  2. 对单日范围复用单日数据。 避免区间与结束日两个接口重复查询同一天,验证缺失值、累计里程、来源优先级和前一日统计口径后再替换。
  3. 减少首次查询传输量。 上游若提供区间聚合结果,可直接获取每车汇总及每日总量;明确车牌查询可考虑传入车牌限制,但必须保留现有权限检查和筛选候选项语义。若继续只提供明细游标分页,长区间首次查询仍受串行页数限制。

未通过缩短超时、隐藏等待动画或并发重试来声称已解决单次查询耗时。

验证

  • TypeScript 检查通过。
  • 监控查询模型、日期范围及里程显示相关 12 项测试通过。
  • Vite 生产构建通过,保留已有的大资源包提示。
  • 浏览器真实接口检查:修改两个日期没有监控请求,点击查询后发送一条包含两个最终日期的请求。
  • 浏览器自动化使用模拟数据验证 1440px 和 390px 两种宽度,各 11 项交互检查通过,均无页面运行时错误;运行脚本与结果位于工作区上级 outputs/mileage-query-20261027/。模拟测试用于验证请求触发条件,不用于性能结论。