Как порядок соединений влияет на производительность запроса - PullRequest
6 голосов
/ 19 октября 2011

Я испытываю большие различия в производительности по времени в моем запросе, и кажется, что порядок, в котором соединения (внутренние и левые внешние) происходят в запросе, имеет значение Существуют ли "основные правила", в которых должны быть объединения?

Оба они являются частью большего запроса. Разница между ними заключается в том, что левое соединение ставится последним в более быстром запросе.

Медленный запрос: (> 10 минут)

SELECT [t0].[Ref], [t1].[Key], [t1].[Name],  
    (CASE 
        WHEN [t3].[test] IS NULL THEN CONVERT(NVarChar(250),@p0)
        ELSE CONVERT(NVarChar(250),[t3].[Key])
     END) AS [value], 
    (CASE 
        WHEN 0 = 1 THEN CONVERT(NVarChar(250),@p1)
        ELSE CONVERT(NVarChar(250),[t4].[Key])
     END) AS [value2]

FROM [dbo].[tblA] AS [t0]
INNER JOIN [dbo].[tblB] AS [t1] ON [t0].[RefB] = [t1].[Ref]

LEFT OUTER JOIN (
    SELECT 1 AS [test], [t2].[Ref], [t2].[Key]
    FROM [dbo].[tblC] AS [t2]
    ) AS [t3] ON [t0].[RefC] = ([t3].[Ref])

INNER JOIN [dbo].[tblD] AS [t4] ON [t0].[RefD] = ([t4].[Ref])

Ускоренный запрос: (~ 30 секунд)

SELECT [t0].[Ref], [t1].[Key], [t1].[Name],  
    (CASE 
        WHEN [t3].[test] IS NULL THEN CONVERT(NVarChar(250),@p0)
        ELSE CONVERT(NVarChar(250),[t3].[Key])
     END) AS [value], 
    (CASE 
        WHEN 0 = 1 THEN CONVERT(NVarChar(250),@p1)
        ELSE CONVERT(NVarChar(250),[t4].[Key])
     END) AS [value2]

FROM [dbo].[tblA] AS [t0]
INNER JOIN [dbo].[tblB] AS [t1] ON [t0].[RefB] = [t1].[Ref]

INNER JOIN [dbo].[tblD] AS [t4] ON [t0].[RefD] = ([t4].[Ref])

LEFT OUTER JOIN (
    SELECT 1 AS [test], [t2].[Ref], [t2].[Key]
    FROM [dbo].[tblC] AS [t2]
    ) AS [t3] ON [t0].[RefC] = ([t3].[Ref])

Ответы [ 3 ]

9 голосов
/ 19 октября 2011

Обычно порядок ВНУТРЕННИХ СОЕДИНЕНИЙ не имеет значения, поскольку внутренние объединения являются коммутативными и ассоциативными. В обоих случаях у вас все еще есть t0 inner join t4, поэтому не должно иметь значения.

Перефразируя это, SQL декларативен: вы говорите «что хотите», а не «как». Оптимизатор работает по принципу «как» и при необходимости будет переупорядочивать СОЕДИНЕНИЯ, на практике выглядя как ГДЕ и т. Д.

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

Итак, я бы проверил:

  • Вы сказали, что это часть более крупного запроса, поэтому этот раздел менее важен, потому что весь запрос имеет значение.
  • Сложность также можно скрыть с помощью представлений, если любая из таблиц фактически является представлениями
  • Это повторяется, независимо от того, в каком коде заказа выполняется?
  • Чем отличаются планы запроса?

См. Некоторые другие вопросы SO:

1 голос
/ 17 апреля 2014

Если у вас более двух таблиц, важно заказать объединение таблиц.Это может иметь большое значение.Первый стол должен получить подсказку.Первая таблица - это тот объект с наиболее селективными строками.Например: если у вас есть таблица участников с 1 000 000 человек, и вы хотите выбрать только женский пол, а это первая таблица, то вы можете присоединить только 500 000 записей к следующей таблице.Если эта таблица находится в конце порядка соединения (может быть, таблица 4,5 или 6), то каждая запись (наихудший случай 1.000.000) будет объединена.Это включает в себя внутренние и внешние объединения.

Правило: начинайте с наиболее селективной таблицы, затем присоединяйтесь к следующей логически наиболее селективной таблице.

Преобразование функций и улучшение должны выполняться в последнюю очередь.Иногда лучше объединить SQL в скобках и использовать выражения и функции во внешних операторах выбора.

0 голосов
/ 01 июля 2014

По крайней мере, в SQLite я обнаружил, что это имеет огромное значение. На самом деле это не должен быть очень сложный запрос, чтобы разница могла проявиться. Однако мои операторы JOIN были внутри вложенного предложения.

По сути, сначала вы должны начать с самых конкретных ограничений, как указал Кристиан.

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