Низкая производительность поиска в кластерном индексе? - PullRequest
4 голосов
/ 27 августа 2009

У меня есть два запроса:

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 раз быстрее, чем второй. В соответствии с планом выполнения, первый запрос использует два сканирования кластеризованного индекса с «BuildingFloor LIKE 'M%'» в качестве предиката и поиск индекса в ContractRecord для каждого из подвыборов в предложении WHERE (стоимость 40% на к югу от выбора).

Во втором запросе используется поиск кластеризованного индекса с «BuildingFloor LIKE« M% »» в качестве предиката и предикат поиска для ограничений AddressId (стоимость 96%). Подсчитанное количество строк также полностью отсутствует (фактическое значение 250 против 1).

Как улучшить производительность второго запроса? Могу ли я заставить SQL Server выбрать альтернативную стратегию или мне нужно изменить индексы в таблицах?

1 Ответ

8 голосов
/ 27 августа 2009

Подзапросы на строку медленные, как и дизъюнктивные (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%'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...