ВНУТРЕННЕЕ СОЕДИНЯЕТСЯ с тем, где на соединенном столе - PullRequest
0 голосов
/ 11 сентября 2009

Допустим, у нас есть
SELECT * FROM A INNER JOIN B ON [....]

Предполагается, что A имеет 2 строки, а B содержит 1M строк, включая 2 строки, связанные с A:
B будет сканироваться только один раз с "фактическим числом строк", равным 2, верно?

Если я добавлю WHERE в таблицу B:
SELECT * FROM A INNER JOIN B ON [....] WHERE B.Xyz > 10

WHERE будет фактически выполнен до объединения ... Так что если где возвращает 1000 строк, "фактическое количество строк" B будет 1000 ... Я не понимаю .. не должно ли это быть <= 2 ??? </p>

Чего мне не хватает ... почему оптимизатор работает таким образом? (SQL 2008)

Спасибо

Ответы [ 3 ]

2 голосов
/ 11 сентября 2009

Оптимизатор будет работать так, как считает быстрее. Это означает, что если столбец Xyz проиндексирован, а столбец соединения - нет, он, скорее всего, сначала выполнит фильтр xyz. Или, если у вас плохая статистика, поэтому он не знает, что фильтр соединения уменьшит B до двух строк, он сначала выполнит предложение WHERE.

1 голос
/ 11 сентября 2009

Он полностью основан на том, какие индексы доступны для использования оптимизатором. Кроме того, нет оснований полагать, что механизм БД будет выполнять WHERE перед другой частью запроса. Оптимизатор запросов может выполнять запрос в любом понравившемся ему порядке, если возвращаются правильные результаты. Опять же, способ правильно оптимизировать этот тип запроса с помощью стратегически размещенных индексов.

0 голосов
/ 11 сентября 2009

«Отсканировано только один раз» немного вводит в заблуждение. Сканирование таблиц - ужасно дорогая вещь в SQL Server. По крайней мере до SS2005 сканирование таблицы требует чтения всех строк во временной таблице, а затем чтения временной таблицы, чтобы найти строки, соответствующие условию соединения. Таким образом, в худшем случае ваш запрос будет читать и записывать 1M строк, затем пытаться сопоставить 2 строки с 1M строк, а затем удалять временную таблицу (этот последний бит, вероятно, самая дешевая часть запроса). Так что если на B нет пригодных для использования индексов, вы просто в плохом месте.

Во втором примере, если B.Xyz не проиндексирован, происходит полное сканирование таблицы и , имеется вторичное совпадение от 2 до 1000 строк, что даже менее эффективно. Если B.Xyz проиндексирован , должен быть выполнен поиск по индексу и соответствие 2: 1000 - гораздо быстрее и эффективнее.

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

РЕДАКТИРОВАНИЕ: возможно ли для вас "развернуть" строки A и использовать их в качестве статического условия в запросе no-JOIN на B? Мы использовали это в нескольких местах в нашем приложении, где мы объединяем маленькие таблицы (<100 строк) и большие (> 100M строк), чтобы получить отличный эффект.

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