Pau*_*lin 4 sql oracle query-optimization
查询:
SELECT tbl1.*
FROM tbl1
JOIN tbl2
ON (tbl1.t1_pk = tbl2.t2_fk_t1_pk
AND tbl2.t2_strt_dt <= sysdate
AND tbl2.t2_end_dt >= sysdate)
JOIN tbl3 on (tbl3.t3_pk = tbl2.t2_fk_t3_pk
AND tbl3.t3_lkup_1 = 2577304
AND tbl3.t3_lkup_2 = 1220833)
where tbl2.t2_lkup_1 = 1020000002981587;
Run Code Online (Sandbox Code Playgroud)
事实:
在tbl1中对11,000行和tbl2中的3500行的数据库进行解释计划表明它正在对tbl1进行全表扫描.在我看来,如果它可以在tbl1上进行索引查询,它应该更快.
在tbl1中对11,000行和tbl2中的3500行的数据库进行解释计划表明它正在对tbl1进行全表扫描.在我看来,如果它可以在tbl1上进行索引查询,它应该更快.
更新:我尝试了一些你建议的提示,解释成本变得更糟!现在我真的很困惑.
进一步更新:我终于可以访问生产数据库的副本,"解释计划"使用索引和低成本查询显示它.我想有更多的数据(在tbl1中超过100,000行,在tbl2中有50,000行)是让它决定索引是值得的.感谢所有帮助过的人.我仍然认为Oracle性能调优是一种黑色艺术,但我很高兴你们中的一些人理解它.
进一步更新:我已根据前雇主的要求更新了问题.他们不喜欢在谷歌查询中显示他们的表名.我应该知道的更好.
答案很简单:因为优化器需要更多的行来查找,所以它确实找到了.
检查统计数据,它们是最新的吗?检查解释计划中的预期基数是否与实际结果相符?如果不修复与该步骤相关的统计信息.
连接列的直方图可能会有所帮助.Oracle将使用这些来估计连接产生的基数.
当然,您始终可以通过提示强制使用索引
查看优化器的行计数估计值会很有用,这些估计值不在您发布的 SQL Developer 输出中。
我注意到它正在执行的两个索引查找是范围扫描而不是唯一扫描。因此,它对返回的行数的估计很容易偏离很远(无论统计信息是否是最新的)。
我的猜测是,它对 TBL2 的表访问的最终行计数的估计相当高,因此它认为它将在 TBL1 中找到大量匹配项,因此决定进行完整扫描/哈希连接而不是嵌套循环/索引扫描。
为了获得真正的乐趣,您可以在启用事件 10053 的情况下运行查询,并获取显示优化器执行的计算的跟踪。