Когда выгодно ограничивать объединение в SQL Server 2005? - PullRequest
2 голосов
/ 25 марта 2011

Например, скажем, у вас есть запрос, подобный этому:

SELECT *
FROM table1 t1
JOIN table2 t2 ON t1.field1 = t2.field1 AND t1.year = t2.year
JOIN table3 t3 ON t1.field1 = t3.field1 AND t1.year = t3.year
JOIN table4 t4 ON t3.field2 = t4.field2 AND t3.year = t4.year
WHERE t1.year = '2010'

Это быстрее сделать:

SELECT *
FROM table1 t1
JOIN table2 t2 ON t1.field1 = t2.field1 AND t1.year = t2.year AND t2.year = '2010'
JOIN table3 t3 ON t1.field1 = t3.field1 AND t1.year = t3.year AND t3.year = '2010'
JOIN table4 t4 ON t3.field2 = t4.field2 AND t3.year = t4.year AND t4.year = '2010'
WHERE t1.year = '2010'

Не всегда очевидно, что будет «быстрее». Иногда план выполнения в SQL Server 2005 говорит, что один быстрее другого, в зависимости от индексации. Иногда выполняется сопоставление хешей, которое, по-видимому, требует интенсивной загрузки ЦП по сравнению с сортировкой, а не объединением слиянием, которое представляется более интенсивным при вводе-выводе. Реальные результаты не всегда отражают то, что можно ожидать, учитывая результаты плана выполнения.


Может кто-нибудь прояснить мне несколько простых сценариев, где один лучше другого? Или хотя бы проверить правильность моего понимания? Мне кажется, что если вы объединяете столбцы с хорошей индексацией, эффективнее не ограничивать объединение годом или каким-либо другим фрагментом данных, поскольку он может использовать сопоставление хеш-функций на основе индекса и не нуждается в сортировать и использовать временную таблицу.

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


Кроме того, меня беспокоит, что выбор перед объединением из таблицы2 не учитывает ограниченный поднабор значений, которые возникают в результате предложения where в таблице table1, он, по-видимому, выбирает все строки из таблицы2, когда не используется ограничение на присоединиться. Поскольку строки из таблицы1 будут ограничены b ГДЕ t1.year = '2010', а объединение ограничено t1.year = t2.year, не следует ли из этого, что объединение должно будет смотреть только на table2, где year = ' 2010' ?

Интересно, почему он не смотрит сначала на предложение where, а выбирает только совпадающие строки, прежде чем он даже выполнит соединение, я уверен, что за этим есть веские причины, но это ускользает от меня, согласно плану выполнения в этом случае количество строк, просмотренных из таблицы 2, меняется в зависимости от того, добавили ли вы t2.year = '2010' в объединение или нет.

Заранее спасибо, и извините за длинный вопрос. Я пытаюсь быть максимально ясным. Прошу прощения за мою неопытность.

Ответы [ 2 ]

5 голосов
/ 25 марта 2011

"Это быстрее?"

Оптимизатор запросов решит, какой фильтр результирующих наборов наиболее ограничен (и, как правило, будет работать хорошо, если ваша статистика актуальна).

1 голос
/ 25 марта 2011

Наличие дополнительного фильтра не добавляет никакой ценности: оптимизатор уже работает. Это делает код сложнее поддерживать, хотя.

Вы можете сделать это для ВНЕШНИХ СОЕДИНЕНИЙ, потому что вы не можете фильтровать WHERE на внешней таблице (изменяется на ВНУТРЕННЕЕ СОЕДИНЕНИЕ):

SELECT *
FROM table1 t1
LEFT JOIN
table2 t2 ON t1.field1 = t2.field1 AND t1.year = t2.year and t2.x = 1
JOIN
table3 t3 on t1.field1 = t3.field1 AND t1.year = t3.year
...
WHERE
t1.year = '2010'
...