You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何LIMIT 10比LIMIT 100执行慢?附执行计划对比分析

为什么LIMIT 10比LIMIT 100执行慢?优化方案解析

问题根源:查询优化器的计划选择偏差

这是典型的优化器基于LIMIT大小做出错误计划选择的案例,核心原因是优化器对符合条件的记录数量估计有误:

  • 当LIMIT 10时,优化器认为:“按dt_rssj的索引(i_T_JDRY_dt_rssj)扫描T_JDRY,逐个关联T_JCYQ找符合条件的记录,应该很快能凑够10条”。但实际情况是,符合T_JCYQ过滤条件的记录极少(最终只返回3条),导致优化器被迫扫描了15万+条T_JDRY记录,每条都要去查询T_JCYQ,绝大多数都不符合过滤条件,所以耗时飙升到3秒多。
  • 当LIMIT 100时,优化器重新评估成本:“先把T_JCYQ里符合所有过滤条件的记录找出来(虽然要扫全表,但符合条件的只有3条),再关联T_JDRY取数据,最后排序”的成本更低,所以选择了先处理T_JCYQ的计划,实际执行只花了60多毫秒。
  • 移除LIMIT后,优化器不再优先考虑“快速获取少量数据”的短平快计划,会选择更适合全量数据的高效关联顺序;删除i_T_JDRY_dt_rssj索引后,优化器没办法走排序索引的计划,只能选择更合理的关联路径,所以速度也显著提升。

优化方案

针对这个场景,有几个实用的优化方向:

1. 强制调整关联顺序(最直接)

重写SQL,明确从过滤条件更多的T_JCYQ表出发进行关联,引导优化器优先处理T_JCYQ的过滤逻辑:

EXPLAIN (analyze,buffers) 
SELECT jdry.c_bh AS rybh, jcyq.c_bh, jdry.c_xm, jdry.c_jdrybm, 
       jcyq.c_jdsbm, jcyq.c_bmbm, jdry.c_fq, jdry.c_fj 
FROM db_szgl.T_JCYQ jcyq
JOIN db_ggfw.T_JDRY jdry ON jdry.c_jdrybm = jcyq.c_jdrybm
WHERE jcyq.c_sfyx <> '0' 
  AND jcyq.c_dqspjg IS NULL 
  AND jcyq.c_lx = '01' 
  AND jcyq.c_dqspzt = '01' 
  AND jcyq.c_jdsbm = '530104' 
ORDER BY jdry.dt_rssj DESC 
LIMIT 10 OFFSET 0

这种写法会让优化器更倾向于先筛选T_JCYQ的符合条件记录,再关联T_JDRY,避免无效的大量扫描。

2. 给T_JCYQ建立针对性复合索引

给T_JCYQ的过滤字段建立复合索引,让优化器可以快速定位符合条件的记录,不用全表扫描:

CREATE INDEX idx_jcyq_filter ON db_szgl.T_JCYQ 
(c_jdsbm, c_lx, c_dqspzt, c_sfyx) 
WHERE c_dqspjg IS NULL;

这个索引包含了所有过滤条件,并且通过WHERE子句限定了c_dqspjg IS NULL的场景,进一步缩小索引范围,提升查询效率。

3. 更新统计信息,修正优化器估计

如果优化器的统计信息过时,会导致它错误估计符合条件的记录数。执行以下命令更新表的统计信息:

ANALYZE db_szgl.T_JCYQ;
ANALYZE db_ggfw.T_JDRY;

更新后,优化器能更准确地判断哪种执行计划成本更低,从而自动选择更优的路径。

4. 禁用不合适的索引(可选)

如果i_T_JDRY_dt_rssj索引在这个查询里经常导致糟糕的执行计划,且该索引不是其他业务必须的,可以考虑删除它;或者使用PostgreSQL的pg_hint_plan插件,通过hint强制不使用该索引:

EXPLAIN (analyze,buffers) 
SELECT /*+ IndexScan(jdry none) */
jdry.c_bh AS rybh, jcyq.c_bh, jdry.c_xm, jdry.c_jdrybm, 
jcyq.c_jdsbm, jcyq.c_bmbm, jdry.c_fq, jdry.c_fj 
FROM db_ggfw.T_JDRY jdry, db_szgl.T_JCYQ jcyq 
WHERE jdry.c_jdrybm = jcyq.c_jdrybm 
  AND jcyq.c_sfyx <> '0' 
  AND jcyq.c_dqspjg IS NULL 
  AND jcyq.c_lx = '01' 
  AND jcyq.c_dqspzt = '01' 
  AND jcyq.c_jdsbm = '530104' 
ORDER BY dt_rssj DESC 
LIMIT 10 OFFSET 0

内容的提问来源于stack exchange,提问作者dodo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:17:22