想象一下,我们有两个表如下:
Trades
(
TradeRef INT NOT NULL,
TradeStatus INT NOT NULL,
Broker INT NOT NULL,
Country VARCHAR(3) NOT NULL
)
CTMBroker
(
Broker INT NOT NULL,
Country VARCHAR(3) NULL
)
(为了本例的目的,这些已被简化)。现在,如果我们希望在Broker列上加入这两个表,并且如果国家/地区存在CTMBroker表中的,我们有以下两种选择:
SELECT T.TradeRef,T.TradeStatus
FROM Trades AS T
JOIN CTMBroker AS B ON B.Broker=T.Broker AND ISNULL(B.Country, T.Country) = T.Country
或
SELECT T.TradeRef,T.TradeStatus
FROM Trades AS T
JOIN CTMBroker AS B ON B.Broker=T.Broker AND (B.COUNTRY=T.Country OR B.Country IS NULL)
这些在逻辑上是等价的,但是在我们的数据库(SQL Server 2008,SP1)的这种特定情况下,为这两个查询生成了两个不同的执行计划,第二个版本在时间和逻辑上明显优于第一个版本读取。
我的问题确实如下:作为一般规则,(2)优先选择(1),或者这恰好恰好利用了2008 SP1中优化器的某些特定特性(因此可能会因未来版本而改变) SQL Server)。
答案 0 :(得分:2)
我认为部分原因是ISNULL是一个函数,因此SQL不能使用表上的任何索引,而是必须扫描评估每一行的表。因此,我试图避免连接条件中的函数。
答案 1 :(得分:1)
你也可以尝试这个吗?
SELECT T.TradeRef,T.TradeStatus
FROM Trades AS T
JOIN CTMBroker AS B ON B.Broker=T.Broker AND B.COUNTRY=T.Country
UNION ALL
SELECT T.TradeRef,T.TradeStatus
FROM Trades AS T
JOIN CTMBroker AS B ON B.Broker=T.Broker AND B.Country IS NULL
UNION ALL通常优于OR,具体取决于优化器优化OR的能力。如果这与第二个查询的速度相同,则说明原因如此之快:优化程序能够看到有两个独立的条件并适当地使用索引。
在第一种情况下,因为您使用的是非sargable函数(ISNULL
),所以无法使用索引。