пятница, 2 октября 2009 г.

Что быстрей LEFT JOIN или подзапрос в SELECT

Часто требуется выбрать дополнительные параметры плюсом к основной выборке.
Это можно сделать двумя способами:
  • LEFT JOIN к основному запросу
  • Подзапрос в секции SELECT
Пример запроса, выбирающего номенклатуру и товарную группу номенклатуры:

Подзапрос в секции SELECT:
SELECT nom.Наименование,
(SELECT tg.Наименование FROM Товарная группа tg WHERE tg.ID = nom.Товарная группа)
FROM Номенклатура nom

Вариант с LEFT JOIN:
SELECT nom.Наименование, tg.Наименование
FROM Номенклатура nom
LEFT JOIN Товарная группа tg
 ON(tg.ID = nom.Товарная группа)

После разбора плана выполнения запроса в MS SQL Server, было выявлено:
  • При выборке в секции SELECT требуется дополнительное время на слияние основной выборки и подзапроса. Вышло 1% от общего времени.(+ LEFT JOIN / - SELECT)
  • Оказалось, что каждый LEFT JOIN выполняется отдельным потоком! В то время как подзапросы выполняются последовательно после основной выборки. (+ LEFT JOIN / - SELECT)
  • Каждый LEFT JOIN объединяется в результирующую выборку, что требует дополнительной памяти. В то время как подзапрос вернет нам одно значение на каждую строку, т.е. для получения результата нам нужно меньше памяти. (- LEFT JOIN / + SELECT)
Вывод: В условиях многоядерных серверов LEFT JOIN имеет неоспоримые преимущества

Ограничения в подзапросах:
При выборке дополнительных параметров в секции SELECT мы можем столкнуться с ситуацией, когда подзапрос вернул нам более одной записи. Отсечь это можно, указав принудительно число выбираемых записей:
SELECT nom.Наименование,
(SELECT TOP 1 tg.Наименование FROM Товарная группа tg WHERE tg.ID = nom.Товарная группа)
FROM Номенклатура nom
Такой запрос выполнялся дольше на 96% по сравнению с аналогичным без TOP 1

Разбор плана показал, что 1% дополнительного времени тратится вложенный цикл, а 95% на просмотр определенных строк не кластеризованного индекса!
Из этого можно сделать один вывод: никогда не используйте без надобности ограничения в подзапросах.

В заключении хотел бы сказать, что бывают ситуации когда без подзапросов не обойтись (группировки, сортировки и т.д.), но использовать их нужно обосновано, если есть возможность, то лучше пользоваться LEFT JOIN.

3 комментария:

  1. Этот комментарий был удален администратором блога.

    ОтветитьУдалить
  2. Самый надежный носитель информации на сегодняшний день ето всетаки, а как вы думали - бумага !
    А программирование особенно LEFT JOIN к основному запросу и подзапрос в секции Select Это - новейший и безкомпромисный метод убивания времени, свободного от жесткого порно или на крайняк беспредельного секаса, и хорошо когда он происходит за счет работодателя или за счет государства. А коли уж заниматься этим то писать лучше с ошибками ибо ошибок не содержит лишь совершенно ненужная программа ! И вообще у программистов должно быть хорошее зрение, что бы видеть сквозь одежду и что бы не бояться секретарш, потому что с ними приходиться работать!
    Вывод : Не надо париться !

    ОтветитьУдалить
  3. Понятно, что человеку свойственно ошибаться.
    Но опыт никто не отменял, нужно постоянно учиться, чтобы не стоять на месте.

    ОтветитьУдалить