SQL Server JOIN с необязательными значениями NULL - PullRequest
1 голос
/ 29 апреля 2010

Представьте, что у нас есть две таблицы:

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), или это просто случайность использования определенной специфической особенности оптимизатора в SP1 2008 (которая может поэтому измениться в будущих версиях) SQL Server).

Ответы [ 2 ]

2 голосов
/ 29 апреля 2010

Я думаю, что отчасти причина в том, что ISNULL является функцией, поэтому SQL не может использовать какие-либо индексы в таблице, но ему приходится просматривать таблицу, оценивая каждую строку. По этой причине я стараюсь избегать функций в условиях соединения.

1 голос
/ 29 апреля 2010

Не могли бы вы попробовать это тоже?

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), индекс использовать нельзя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...