Почему использование временной таблицы будет быстрее, чем вложенный запрос? - PullRequest
5 голосов
/ 13 мая 2010

Мы пытаемся оптимизировать некоторые из наших запросов.

Один запрос выполняет следующие действия:

SELECT t.TaskID, t.Name as Task, '' as Tracker, t.ClientID, (<complex subquery>) Date,
INTO [#Gadget]
FROM task t

SELECT TOP 500 TaskID, Task, Tracker, ClientID, dbo.GetClientDisplayName(ClientID) as Client 
FROM [#Gadget]
order by CASE WHEN Date IS NULL THEN 1 ELSE 0 END , Date ASC

DROP TABLE [#Gadget]

(Я удалил сложный подзапрос. Не думаю, что он уместен, кроме как объяснить, почему этот запрос был выполнен в два этапа.)

Я думал было бы гораздо эффективнее объединить это в один запрос, используя подзапросы как:

SELECT TOP 500 TaskID, Task, Tracker, ClientID, dbo.GetClientDisplayName(ClientID)
FROM
(
    SELECT t.TaskID, t.Name as Task, '' as Tracker, t.ClientID, (<complex subquery>) Date,
    FROM task t
) as sub    
order by CASE WHEN Date IS NULL THEN 1 ELSE 0 END , Date ASC

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

Но оказывается, что это намного медленнее. 8 секунд против 5 секунд.

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

Что мне не хватает?

Редактировать -

Из того, что я смог увидеть из планов запросов, оба в значительной степени идентичны, за исключением временной таблицы, в которой есть дополнительная операция «Вставка таблицы» со стоимостью 18%.

Очевидно, что при наличии двух запросов стоимость Sort Top N намного выше во втором запросе, чем стоимость Sort в методе подзапроса, поэтому сделать прямое сравнение затрат сложно.

Все, что я вижу по планам, будет означать, что метод подзапроса будет быстрее.

Ответы [ 3 ]

4 голосов
/ 13 мая 2010

«должен быть» - опасная вещь для производительности базы данных. Я часто обнаруживал, что временные таблицы ускоряют, иногда значительно. Простое объяснение состоит в том, что оптимизатору легче избежать повторения работы.

Конечно, я также видел, что временные таблицы замедляют, а иногда и медленнее.

Ничто не заменит профилирование и изучение планов запросов (однако, прочитайте их оценки с недоверием).

3 голосов
/ 13 мая 2010

Очевидно, что SQL Server выбирает неправильный план запроса. Да, это может случиться, у меня был точно такой же сценарий, как и у вас несколько раз.

Проблема в том, что оптимизация запроса (вы упомянули «сложный подзапрос») является нетривиальной задачей: если у вас n таблиц, их примерно n! возможные заказы на присоединение - и это только начало. Таким образом, вполне вероятно, что выполнение (а) сначала вашего внутреннего запроса и (б) затем внешнего запроса - хороший путь, но SQL Server не может получить эту информацию в разумные сроки.

Что вы можете сделать, это help SQL Server. Как пишет Дэн Тау в своей великой книге « Настройка SQL », ключом обычно является порядок соединения, переходящий от самой селективной к наименее селективной таблице. Используя здравый смысл (или метод, описанный в его книге, который намного лучше), вы можете определить, какой порядок соединения будет наиболее подходящим, а затем использовать подсказку запроса FORCE ORDER.

В любом случае, каждый запрос уникален, нет «волшебной кнопки», чтобы сделать SQL Server быстрее. Если вы действительно хотите узнать, что происходит, вам нужно посмотреть (или показать нам) планы запросов ваших запросов. Другие интересные данные представлены в SET STATISTICS IO , который сообщит вам, какой (дорогой) доступ к жесткому диску обеспечивает ваш запрос.

0 голосов
/ 12 сентября 2013

Я повторил этот вопрос здесь: Как заставить принудительно выполнить подзапрос так же, как таблицу #temp?

Суть в том, да, я понимаю, что иногда оптимизатор вправе вмешиваться в ваши подзапросы, как будто они не полностью самодостаточны, но иногда он делает неверный поворот, когда пытается быть умным в некотором смысле. что мы все знакомы Я говорю, что должен быть способ отключить эту «хитрость» там, где это необходимо, вместо того, чтобы разрушать подход под руководством View с временными таблицами.

...