为什么where子句中无用的语句会降低sql查询速度?

时间:2013-01-17 08:18:02

标签: database oracle

我在下面有两个问题:

SELECT cl.`cl_boolean`, l.`l_name`
FROM `card_legality` cl
LEFT JOIN `legality` l ON l.`legality_id` = cl.`legality_id`
WHERE cl.`card_id` = 23155


SELECT cl.`cl_boolean`, l.`l_name`
FROM `card_legality` cl
LEFT JOIN `legality` l ON l.`legality_id` = cl.`legality_id`
WHERE cl.`card_id` = 23155 or 1 = 2

(这不是真实的情况,只是显示问题)

我想知道为什么第二个这么慢(在真实情况下差不多100倍)。

好的,下面是我的案例中的查询(oracle):

select *
from LA_TESTCASE this_ 
left outer join LA_RULE   rule1_    on this_.ROOTCAUSE_RULE_ID = rule1_.ID 
left outer join LA_TEST   test2_    on this_.TEST_ID = test2_.ID 
left outer join LA_SUITE  suite3_   on test2_.SUITE_ID = suite3_.ID 
left outer join LA_RUN    run4_     on suite3_.RUN_ID = run4_.ID
where (run4_.NAME = 'RRP_XO-245'/* or 1 = 2*/)
order by this_.ID desc;

它与示例案例几乎相同。

2 个答案:

答案 0 :(得分:2)

“它与样本案例几乎相同。”实际上它并不像它。

在第一种情况下,您在左连接的左表上进行过滤。在第二个中,您将过滤查询的右侧(外部联接表)。

在这种情况下,OR 1=2的存在很可能导致全表扫描解决它(再次,运行解释计划以查看此内容)。

但你的查询没有任何意义,因为你在外部加入RUN4_,然后在WHERE子句中对它进行过滤(而不是连接本身)。

run4_.NAME = 'RRP_XO-245'

你应该整理查询的逻辑。

答案 1 :(得分:1)

在这种情况下,原因是OR

在第一个查询中,引擎可能会在card_id上使用索引。它可能使用散列连接来连接两个表。

在第二个中,OR的存在导致存在更多可能没有card_id = 23155的行的可能性。所以,索引是无用的:它应该扫描整个表。

此外,通常or条件更难放入散列连接中,因此可能会强制执行NESTED LOOOPS JOIN。