我有两个问题:
SELECT SELECT NamesRecord.NameID, NamesRecord.FulfillmentAddressID NameFulfillmentAddressID, ContractRecord.FulfillmentAddressID, ContractRecord.BillingAddressId
FROM Magnet.dbo.ContractRecord ContractRecord
INNER JOIN Magnet.dbo.NamesRecord NamesRecord
ON NamesRecord.NameId = ContractRecord.DonorId
WHERE NameID > -1
AND (EXISTS (
SELECT 1
FROM Magnet.dbo.AddressRecord AddressRecord
WHERE AddressRecord.AddressId = ContractRecord.FulfillmentAddressId
AND BuildingFloor LIKE 'M%')
OR EXISTS (
SELECT 1
FROM Magnet.dbo.AddressRecord AddressRecord
WHERE AddressRecord.AddressId = ContractRecord.BillingAddressId
AND BuildingFloor LIKE 'M%'))
SELECT SELECT NamesRecord.NameID, NamesRecord.FulfillmentAddressID NameFulfillmentAddressID, ContractRecord.FulfillmentAddressID, ContractRecord.BillingAddressId
FROM Magnet.dbo.ContractRecord ContractRecord
INNER JOIN Magnet.dbo.NamesRecord NamesRecord
ON NamesRecord.NameId = ContractRecord.DonorId
WHERE NameID > -1
AND (EXISTS (SELECT 1
FROM Magnet.dbo.AddressRecord AddressRecord
WHERE AddressRecord.AddressId IN (ContractRecord.FulfillmentAddressId, ContractRecord.BillingAddressId)
AND BuildingFloor LIKE 'M%'))
第一个查询运行速度比第二个快10多倍。根据执行计划,第一个查询使用两个Clustered Index Scans,其中“BuildingFloor LIKE'M%'”作为谓词,并在ContractRecord上使用WHERE子句中的每个子选项进行索引搜索(每个成本40%)子选择)。
第二个查询使用Clustered Index Seek,其中“BuildingFloor LIKE'M%'”作为谓词,并使用AddressId约束的搜索谓词(96%成本)。估计行数也完全没有(实际为250,估计为1)。
如何改善第二个查询的性能?我可以强制SQL Server选择替代策略,还是必须修改表上的索引?
答案 0 :(得分:8)
每行子查询和分离(or
)过滤条件一样慢。完全摆脱子查询,如果您在过滤器中使用or
谓词,则可以考虑将其替换为union
。在内部,in
被转换为or
。
select
NamesRecord.NameId
from (
select
ContractRecord.DonorId,
ContractRecord.FulfillmentAddressId as AddressId
from Magnet.dbo.ContractRecord ContractRecord
union
select
ContractRecord.DonorId,
ContractRecord.BillingAddressId as AddressId
from Magnet.dbo.ContractRecord ContractRecord
) ContractRecordInfo
join Magnet.dbo.NamesRecord NamesRecord on 1=1
and NamesRecord.NameId = ContractRecordInfo.DonorId
and NamesRecord.NameId > -1
join Magnet.dbo.AddressRecord AddressRecord on 1=1
and AddressRecord.AddressId = ContractRecordInfo.AddressId
and AddressRecord.BuildingFloor like 'M%'