早上九点半,运营打开留存看板,进度条转了十几秒;分析师跑一条漏斗查询,等了五分钟;数据开发在补昨天的分区,顺手把夜间任务又往后挪了一小时。三个场景都被叫作分析慢,处理方式却完全不同。有人加机器,有人改 SQL,有人把看板图表砍掉一半,结果常常只解决了其中一处。
海量数据分析的耗时,通常分散在数据扫描、模型计算、查询执行、资源排队和前端渲染几个环节。先量出时间花在哪一段,再选对应动作,比直接堆资源更可靠。下面这套五层排查,适合数据团队负责人、分析师、数据开发和平台运维一起使用。如果团队正在梳理从指标到问数的完整链路,可以先看这份 AI 数据分析指南。
先把慢在哪一段量清楚
每次排查先固定四类信息:数据规模、并发、时延、资源。缺少其中任何一类,后面的判断都容易变成猜测。
| 指标 | 怎么取 | 用来判断 |
|---|---|---|
| 扫描字节与扫描行数 | 查询详情或执行计划 | 数据量影响有多大,分区和列裁剪是否生效 |
| 执行时间与排队时间 | 查询历史或监控平台 | 慢在计算本身,还是慢在等待资源 |
| 并发数与高峰时段 | 查询日志、看板访问记录 | 是否需要负载隔离、错峰或限流 |
| CPU、内存、IO、网络 | 系统监控 | 哪类资源先到瓶颈 |
| 前端加载与渲染时间 | 浏览器性能面板 | 查询快但页面慢时,问题在哪一段 |
| 结果行数与传输大小 | 查询结果、网关日志 | 传输和渲染是否被大结果拖慢 |
P95 指 95% 的请求完成时间,能反映长尾等待。平均耗时容易掩盖少数极慢查询,排查时优先看 P95 和最大耗时。
同一句 SQL,在早上九点和凌晨两点跑,耗时可能差出数倍。对照测试要固定数据时间窗、并发条件和查询参数,每次只改一个变量。
先记录基线,再做改动;没有基线的优化,很难证明有效。
第一层,数据量先看扫描范围
判断数据量的影响,先看查询实际读取的字节数。表的总行数只说明存量,扫描范围更接近真实成本。一个看板只需要最近 7 天数据,却扫了 365 天,问题就在过滤条件或分区设计。
BigQuery 文档对分区裁剪的解释很直接:查询在分区列上带过滤条件时,引擎只扫描匹配的分区,跳过其余分区。聚簇则按列对数据排序,让引擎只读取相关存储块。两者可以叠加使用。
判断扫描是否合理,看三个信号:扫描字节、命中分区数、扫描行数与返回行数的比例。
分区和聚簇怎么选
按时间分区适合有明确时间范围、需要按周期保留或清理的数据。聚簇更适合多列过滤、聚合或高基数列。Google Cloud 文档提到,分区会生成较小的数据块,约 10GB 量级;分区数量很多时会增加元数据开销,查询时也会影响元数据访问。用多张日期分片表代替分区表,同样会增加查询开销。
过滤条件要能直接作用在分区列上。对分区列套函数、做隐式类型转换,可能让裁剪失效,需要在执行计划里确认实际扫描范围。列裁剪同样重要,分析查询只取需要的列,宽表里的长文本和 JSON 字段如果没有用到,读取它们只会增加 IO 和传输。
同样一张十亿行表,命中一个分区和扫描全表,代价可能相差几个数量级。
第二层,数据模型把重复计算前移
如果同一批指标每天被几十个看板重复计算,每次都从明细表重新聚合,查询层再优化也很难快。把稳定的口径做成宽表、汇总表或物化视图,可以让重复计算只发生一次。
物化视图适合结果可复用、查询模式稳定的场景。Snowflake 文档说明,物化视图存储预先计算的结果,查询时直接读取;它只覆盖视图包含的行和列,并且会带来存储和计算成本。基表更新频繁时,刷新成本可能超过节省的查询时间,需要把刷新频率和新鲜度要求一起评估。
预聚合的适用条件有三个:查询模式相对固定、结果被多处复用、业务能接受一定延迟。探索式分析、临时维度组合、口径还在频繁调整的指标,放进预聚合表反而会增加维护负担。
指标口径分散是另一个隐性成本。同一个留存率在三个团队有三套 SQL,排查时很难判断是数据慢还是口径不一致。把指标定义、维度和过滤条件收进统一语义层,能减少重复开发和结果对不上的情况。相关做法可以参考 Agent 语义层建设指南。
预聚合解决重复计算,语义层解决重复定义,两件事要分开做。
第三层,查询与执行计划找出最贵的算子
扫描量正常,查询仍然慢,下一步看执行计划。不同引擎的展示方式不同,通常都能看到扫描、过滤、聚合、join、排序、数据交换和落盘这些环节。
四个常见信号
| 信号 | 可能原因 | 对应动作 |
|---|---|---|
| 扫描字节远大于结果所需 | 未命中分区、全列扫描 | 补分区过滤、列裁剪 |
| shuffle 数据量大 | join 顺序不当、聚合基数高 | 提前过滤、预聚合、调整 join |
| 单个任务耗时远高于其他任务 | 数据倾斜 | 拆分热点键、加盐、两阶段聚合 |
| 落盘或内存溢出 | 并行度不足、数据膨胀 | 增加内存、调整并行度、拆分查询 |
shuffle 指查询过程中按 join 键或聚合键重新分发数据,数据量越大,网络和磁盘压力越高。这些信号需要结合引擎的实际指标看。以 Snowflake 为例,查询加速适合大扫描加高选择性过滤的查询;物化视图和聚簇各有适用的查询类型。换引擎之前,先把当前引擎的能力用到位。
常见改法
- 把过滤条件下推到最内层,减少后续 join 和聚合的数据量
- 只选必要列,避免 SELECT *
- 拆分一次生成几十个指标的巨型 SQL,按主题分步落中间结果
- 检查 join 键类型是否一致,避免隐式转换
- 对倾斜键单独处理,或先聚合再 join
- 探索阶段限制返回行数,分页取结果
- 业务允许近似结果时,使用近似去重函数
改 SQL 前保留原语句和执行计划,改完用同一数据时间窗复跑,确认结果行数、核心指标和耗时都符合预期。
执行计划里最贵的算子,通常就是下一步该动的地方。
第四层,资源与并发先看排队再谈扩容
查询本身没有明显问题,所有查询在高峰一起变慢,重点转向资源与并发。先区分三种情况:单条查询算力不足、多条查询争用资源、任务排队等待。
排队时间是关键信号。执行时间不长、排队时间持续上升,说明并发超过了当前资源池的承载能力。Snowflake 文档提到,仓库越大,可用于执行查询的计算资源越多,对复杂查询的提升更明显;仓库负载过重时,并发查询会争用资源,单纯扩容未必带来预期提升。扩容后如果性能提升抵不过成本增加,可以回退到原规格。
负载隔离往往比重扩容更早见效。把夜间跑批、临时取数、看板查询分到不同资源组或队列,能减少互相拖累。跑批任务错峰,限制单个用户的并发查询数,给高频看板结果做缓存,这些动作的成本通常低于直接扩到最大规格。
扩容前先回答两个问题:瓶颈是单查询并行度不足,还是多查询争抢资源。前者扩容可能有效,后者要先做隔离和限流。
先看排队时间,再决定扩容;仓库已经过载时,扩容的收益会被争用抵消一部分。
第五层,看板与前端查询快不等于打开快
SQL 在数据库里 1 秒返回,用户打开看板仍可能等 10 秒。把一次看板加载拆成三段:查询执行、结果传输、前端渲染。
查询执行看前面四层。结果传输看返回行数、列数和网络。前端渲染看图表的 DOM 数量、表格行数、是否在浏览器里做二次计算。
先做低成本的减法
- 默认时间范围从 30 天改为 7 天,让用户主动延长
- 首屏只加载核心图表,其余图表懒加载
- 大表格分页,不做一次性全量渲染
- 高频且变化不快的指标走缓存或预计算
- 合并重复图表,减少同一查询的多次调用
- 导出任务异步执行,避免阻塞页面
缓存要处理新鲜度和失效。数据更新后仍返回旧结果,业务会很快失去信任。按指标设置缓存时长,在数据写入完成时主动失效,比统一缓存 10 分钟更稳妥。
查询 1 秒、页面 10 秒,问题通常在传输或渲染。
一张表定位按七步处理
| 现象 | 优先检查 | 判别信号 | 先做什么 | 谨慎做什么 |
|---|---|---|---|---|
| 所有查询在高峰变慢 | 资源与并发 | 排队时间上升、CPU 持续打满 | 负载隔离、错峰、限并发 | 直接扩到最大规格 |
| 单条查询一直慢 | 查询与模型 | 扫描字节正常但 shuffle 大、单任务长尾 | 改 SQL、处理倾斜、预聚合 | 先加资源 |
| 扫描字节远大于结果所需 | 数据层 | 未命中分区、全列扫描 | 补分区过滤、列裁剪、聚簇 | 盲目增加物化视图 |
| 看板打开慢但 SQL 快 | 前端与传输 | 查询小于 1 秒,渲染数秒 | 减图表、分页、缓存、懒加载 | 只优化 SQL |
| 夜间跑批拖到早上 | 调度与资源 | 任务重叠、队列等待 | 错峰、拆任务、独立资源组 | 无限扩大并发 |
| 同一指标结果不一致 | 模型与口径 | 多套 SQL 口径 | 统一语义层、固定指标定义 | 用缓存掩盖差异 |
具体处理顺序可以按七步走:
- 定义症状和目标,例如看板 P95 从 12 秒降到 3 秒以内
- 记录基线:数据规模、并发、P95、扫描字节、排队时间、资源利用率
- 看扫描:分区命中、列裁剪、聚簇是否生效
- 看计划:shuffle、join、倾斜、落盘
- 看排队与资源:执行时间与排队时间的比例
- 看前端:查询、传输、渲染各占多少
- 单变量修改,复跑对照,验证结果与成本,保留回滚
这张表不能替代执行计划,但能帮助团队在半小时内缩小范围,避免所有人同时改 SQL、加机器、删图表。
提速后怎么验证怎么回滚
验证至少看五个指标:P95 时延、扫描字节、排队时间、单次查询成本、结果一致性。只比较平均耗时容易掩盖长尾,P95 更能反映用户实际等待。
对照测试怎么做
- 使用同一份数据快照或同一时间窗
- 固定并发和查询参数
- 每次只改一个变量
- 在高峰和低峰各跑一轮
- 重复三次以上,比较分布
- 核对结果行数和核心指标
上线采用灰度切换,保留原 SQL、原模型和原资源配置。出现结果异常、成本上升或长尾变差时,能在一个开关内回退。
提速可能带来成本上升。扫描量减少通常同时降成本;扩容、物化视图和缓存则可能增加存储或计算费用。把查询频率和单次成本一起算,才能判断优化是否值得。
P95 时延、扫描字节、排队时间、单次成本、结果一致性,五项一起看。
数据分析 Agent 能接住哪一段
前面的五层处理的是计算链路。分析慢还有一段常被忽略:业务提出问题,分析师理解需求、找表、写 SQL、核对口径、做图,再回到业务确认。这段路径常常占掉数小时。
数据分析 Agent 适合承接这一段。用自然语言发起查询,多轮追问细化条件,自动做归因和可视化,把常见分析任务从排期取数变成对话完成。ThinkingAI 的企业级 AI Agent 平台在这些场景中提供数据分析 Agent 能力,覆盖用户行为分析、漏斗、留存、路径、归因和看板等传统分析能力,已服务全球 1500 家企业、接入超过 8000 款产品。
它适合三类任务:业务人员的日常问数、分析师的探索式分析、异常发生后的第一轮归因。涉及大规模明细扫描、复杂模型重算和高并发看板的任务,仍然依赖前面的数据、模型、查询和资源优化。
落地前要准备三件事:统一指标口径、可用的数据权限、可验证的结果。Agent 生成的查询和结论要能回到原始数据核对,性能也要在真实负载下测试。相关能力可以查看 数据分析 Agent 页面。
Agent 缩短的是人找答案的路径,底层扫描、计算和排队仍要按五层处理。
常见问题
扩容后仍然慢,先查什么
先看排队时间和扫描字节。排队时间高、CPU 持续打满,说明并发争用,优先做负载隔离和限流;扫描字节远大于结果所需,说明分区或列裁剪没生效,扩容只能缓解一部分。单条查询本身并行度不足时,扩大规格才更可能有效。
分区和聚簇怎么选
有时间范围、需要按周期保留或清理的数据,优先按时间分区。经常按多列过滤、聚合或 join 的字段,考虑聚簇。两者可以组合。分区粒度过细、单分区数据量很小时,元数据开销会上升,需要结合实际扫描效果评估。
物化视图和缓存怎么取舍
物化视图把计算前移到数据层,适合稳定的聚合结果和多处复用;缓存把结果放在查询链路前端,适合变化不快、重复访问的看板。物化视图要承担刷新和存储成本,缓存要处理失效和一致性。两者都可以用,但都要能回答命中率和新鲜度两个问题。
看板慢但 SQL 很快,问题在哪
按查询、传输、渲染三段拆。查询小于 1 秒但页面仍慢,先看返回行数和列数,再看图表数量、表格渲染和浏览器二次计算。减少首屏图表、分页、懒加载和缓存,通常比继续优化 SQL 更有效。
数据分析 Agent 能自动优化慢查询吗
Agent 可以帮助解释执行计划、改写查询、定位异常,但查询速度仍取决于数据布局、模型、资源和并发。高风险改动需要人工复核,优化结果要在真实负载下对照验证。把它当作分析和排查的助手,比当作自动调优开关更稳妥。
参考资料
- Snowflake 官方文档,《优化查询性能》:https://docs.snowflake.cn/zh/en/user-guide/performance-query-options
- Snowflake 官方文档,《增加仓库规模》:https://docs.snowflake.cn/zh/en/user-guide/performance-query-warehouse-size
- Google Cloud 官方文档,《分区表简介》:https://docs.cloud.google.cn/bigquery/docs/partitioned-tables?hl=zh-cn
以上文档查阅于 2026 年 10 月,具体能力以各产品当前版本文档为准。






