同一查询在两数据库中选用不同索引的原因及数据影响咨询
同一SQL在不同数据库执行计划差异的原因分析
问题背景
我编写了如下SQL查询语句,在两个数据内容不同的数据库(记为A和B)中执行时,得到的执行计划存在差异:
SELECT * FROM voucher_row_tab g, voucher_type_tab v WHERE g.company = '12' AND (g.voucher_date BETWEEN to_date('2022-12-10', 'YYYY-MM-DD') AND to_date('2023-12-10', 'YYYY-MM-DD')) AND (g.account BETWEEN '100' AND '200') AND g.company = v.company AND g.voucher_type = v.voucher_type AND v.simulation_voucher != 'TRUE' AND 'TRUE' = (SELECT TEST_API.CHECK (g.company, g.pc_id) FROM DUAL);
注:原SQL中AND ('2023-12-10', 'YYYY-MM-DD')存在语法错误,已修正为AND to_date('2023-12-10', 'YYYY-MM-DD')
两个数据库均已定义以下两个索引:
- 索引1:
<COMPANY, ACCOUNTING_PERIOD, ACCOUNTING_YEAR, VOUCHER_TYPE> - 索引2:
<PC_ID, COMPANY, ACCOUNTING_YEAR>
数据库A选用索引1,数据库B选用索引2,请问造成该差异的原因是什么?数据内容是否会对此产生影响?
核心原因及分析
1. 统计数据差异是核心驱动
数据库优化器选择索引的核心依据是表和索引的统计数据,两个库的数据内容不同,导致统计信息(比如表的总行数、列的基数、数据分布区间、过滤条件的命中行数)完全不一致:
- 对索引1:如果数据库A中
company='12'的过滤条件能筛选出极小比例的行,优化器会判定通过索引1快速定位数据后,再处理后续关联、子查询的成本更低。 - 对索引2:SQL中存在依赖
pc_id的API调用子查询,数据库B的统计数据可能显示pc_id的分布更集中,或者通过索引2获取pc_id后,能大幅减少API的无效调用次数,整体成本更优。
2. 数据内容直接影响索引选择
数据内容的差异是根本因素:
- 若数据库A中
voucher_date和account的组合过滤返回的数据集极小,优化器会优先用包含COMPANY的索引1定位数据,再推进后续逻辑。 - 若数据库B中满足
company='12'且API返回TRUE的pc_id占比更高,或者pc_id的重复率低,优化器会认为通过索引2获取pc_id能更高效地匹配子查询条件,降低整体执行成本。
3. 其他潜在影响因素
- 两个数据库的优化器参数(如
optimizer_mode、optimizer_index_cost_adj)可能存在差异,导致成本计算逻辑不同。 voucher_type_tab的数据量、索引情况在两个库中不一致,会影响关联操作的成本评估,进而反向影响voucher_row_tab的索引选择。
结论
数据内容确实会直接影响执行计划的选择,核心原因是不同数据库的统计数据、数据分布、过滤条件的命中规模存在差异,导致优化器对两个索引的成本计算结果不同,最终选择了不同的执行路径。
内容的提问来源于stack exchange,提问作者lse23
相关产品推荐
相关产品推荐

