Производительность SQL Query UNION - PullRequest
1 голос
/ 27 марта 2012

UPDATE

Я думаю, что преждевременно спрашивать об этом. После нескольких тестов я обнаружил, что производительность не улучшилась. Я выполню еще несколько тестов и опубликую обновления здесь. До сих пор не удосужился ответить на этот вопрос.

У меня был такой запрос ...

SELECT DISTINCT TOP 11 [Field_A] 
FROM   [#TempTable] 
WHERE  [Field_A] NOT IN (SELECT bo.[Id] 
                         FROM   [BusinessObject_Table] bo 
                         UNION 
                         SELECT boTemp.[Id] 
                         FROM   [#BusinessObject_Table] boTemp) 

Этот запрос выполняется вечно для большого набора данных. Я также добавил индекс CLUSTERED в столбец Id таблиц Temp, что дало некоторый прирост производительности, но завершить не удалось.

Я заменил этот запрос на этот ...

SELECT DISTINCT TOP 11 [Field_A] 
FROM   [#TempTable] 
WHERE  [Field_A] NOT IN (SELECT bo.[Id] 
                         FROM   [BusinessObject_Table] bo) 
       AND [Field_A] NOT IN (SELECT boTemp.[Id] 
                             FROM   [#BusinessObject_Table] boTemp) 

Это завершено в секундах. Может кто-нибудь объяснить, что здесь произошло?

ОБНОВЛЕНИЕ: Я думал, что оба запроса одинаковы. Это то, что мне нужно.

BusinessObject_Table has following Ids: 1, 2, 3

#BusinessObject_Table has: 3, 4, 5

TempTable has rows whose Field_A values are: 1, 2, 3, 4, 6

Результат запроса должен быть: 6 (Обратите внимание на изменение в запросе выше)

Я постараюсь получить планы запросов и опубликовать их здесь.

Ответы [ 2 ]

3 голосов
/ 27 марта 2012

Гадание при отсутствии планов запроса ...

СОЮЗ в подзапросе вызывает ОТЛИЧИЕ. С отдельными предложениями IN этого избегают. Тем не менее, логика отличается между запросами (Edit: как отметил Мартин Смит)

С UNION ALL и одним IN должно быть лучше, если вам нужна эта логика

WHERE  [Field_A] NOT IN (SELECT bo.[Id] 
                     FROM   [BusinessObject_Table] bo 
                     UNION ALL
                     SELECT boTemp.[Id] 
                     FROM   [#BusinessObject_Table] boTemp)
2 голосов
/ 27 марта 2012

Я думаю, вы должны выполнить свой запрос следующим образом:

SELECT DISTINCT TOP 11 [Field_A] 
FROM   [#TempTable] 
WHERE NOT EXISTS(
  SELECT 1 FROM BusinessObject_Table bo WHERE #TempTable.FieldA = bo.Id
) AND NOT EXISTS(
  SELECT 1 FROM #BusinessObject_Table bo WHERE #TempTable.FieldA = bo.Id
) 

Таким образом, SQL Server может использовать свой оптимизатор, вероятно, немного лучше, чем ваш запрос UNIONed. Вполне может быть, что оптимизатор выберет выполнение вашего запроса в другом порядке, в зависимости от ваших стратегий индексирования и размеров таблицы. Скорее всего, это будет самый быстрый способ сделать это. Хотя без структуры таблицы и показанных индексов и планов выполнения трудно быть уверенным.

...