Имеет ли значение порядок предложений where в SQL?


121

Скажем, у меня есть таблица PEOPLEс 3 столбцами ID, LastName, FirstName, ни один из этих столбцов не индексируется.
LastNameявляется более уникальным и FirstNameменее уникальным.

Если я сделаю 2 поиска:

select * from PEOPLE where FirstName="F" and LastName="L" 
select * from PEOPLE where LastName="L" and FirstName="F"

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

Я правильно понимаю?


8
Нет, этот порядок не имеет значения - любой достойный оптимизатор запросов просмотрит все предложения WHERE и найдет наиболее эффективный способ удовлетворить этот запрос
marc_s

3
Каковы были ваши наблюдения, когда вы запускали эти два утверждения? Как выглядели планы выполнения?
Конрад Фрикс,

3
Вы имеете в виду конкретную СУБД? Различия действительно есть.
Bjoern


Ответы:


101

Нет, этот порядок не имеет значения (или, по крайней мере: не имеет значения).

Любой достойный оптимизатор запросов рассмотрит все частиWHERE предложения и наиболее эффективный способ удовлетворить этот запрос.

Я знаю, что оптимизатор запросов SQL Server выберет подходящий индекс - независимо от того, в каком порядке у вас есть два условия. Я предполагаю, что другие СУБД будут иметь аналогичные стратегии.

Важно то, есть ли у вас для этого подходящий индекс!

В случае с SQL Server он, скорее всего, будет использовать индекс, если у вас есть:

  • указатель на (LastName, FirstName)
  • указатель на (FirstName, LastName)
  • индекс только (LastName)или только (FirstName)(или оба)

С другой стороны - опять же для SQL Server - если вы используете SELECT *для захвата всех столбцов из таблицы, а таблица довольно мала, тогда есть большая вероятность, что оптимизатор запросов просто выполнит сканирование таблицы (или кластерного индекса) вместо использования индекс (потому что поиск на полной странице данных для получения всех остальных столбцов очень быстро становится слишком дорогим).


Если нет индекса (ов), операция может быть правильной, в зависимости от данных. Конечно, делать такое без индексов было бы странным решением ...
Тони Хопкинсон

@TonyHopkinson: Я так не думаю - даже без индексов я сомневаюсь, что есть какая-то разница. В конце концов: что еще, кроме полного сканирования таблицы, может РСУБД без индексов?
marc_s

2
Интересное примечание к SQL-серверу: очевидно, что порядок НЕ СУЩЕСТВУЕТ в предикатах действительно может влиять на создание плана: bradsruminations.blogspot.com/2010/04/looking-under-hood.html
Джастин Свартсел

3
Странно то, что при первом выполнении запроса порядок условий в предложении WHERE ДЕЙСТВУЕТ! У меня было два условия, что-то вроде: WHERE T1.col_1/T2.col_2 > 10 AND T2.col_2 <> 0и я получил DIVIDE BY 0ошибку. После того, как я поменял порядок, условия запрос выполнился успешно. Затем я переключил порядок обратно, чтобы снова получить сообщение об ошибке, но на этот раз это сработало! В конце концов я пришел к выводу, что при первом запуске порядок имеет значение, пока не будет построен план выполнения. После этого порядок не изменится. 'не имеет значения', потому что план оптимизатора / исполнительного директора позаботится об этом
Radu Gheorghiu

1
Мне нравится, что вы сказали: «... или, по крайней мере, не имеет значения» - полностью согласен. К сожалению, иногда это имеет значение. Я видел случаи, когда SQL был слишком сложным для обработки оптимизатором, и такие вещи, как порядок столбцов и порядок соединения таблиц, действительно имели значение. Это зависит от СУБД, сложности оператора SQL и даже от выпуска. Очень сложный SQL может привести к неправильным решениям оптимизатора или использованию жестко заданных значений по умолчанию в коде оптимизатора.
Виктор Ди Лео

19

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

Не думайте, что SQL заботится о порядке. Следующее вызывает ошибку в SQL Server:

select *
from INFORMATION_SCHEMA.TABLES
where ISNUMERIC(table_name) = 1 and CAST(table_name as int) <> 0

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


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

7
@ Джим Если ISNUMERIC(table_name) = 1 был вычислен первым, то CASTбудет вызываться только для числовых имен таблиц. Но поскольку он не вычисляется первым, CASTон также оценивается для нечисловых имен таблиц, вызывая сообщение об ошибке.
hibbelig

2
Отличное осветление
neeohw

Просто чтобы быть уверенным, что я проверил, приведет ли подстановка условий к тому, что SQL-сервер будет обрабатывать их наоборот, но он не работает в обоих направлениях. Я думаю, это может означать одно из двух: (1) это не оптимизация так хорошо, как могла бы, или (2) это ошибка времени компиляции, и SQL даже не начинает пытаться что-либо сравнивать, предварительно спасаясь. Я предполагаю, что это номер. 2.
Луи Сомерс

9

ANSI SQL Draft 2003 5WD-01-Framework-2003-09.pdf

6.3.3.3 Порядок оценки правил

...

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

скопировано отсюда


2

Нет, все RDBM сначала начинают с анализа запроса и его оптимизации, переупорядочивая предложение where.

В зависимости от того, какую RDBM вы используете, может отображать результат анализа (например, поиск плана объяснения в oracle)

М.


Это делается на основе индексов. Так что это косвенно с точки зрения содержания.
Тони Хопкинсон

1

Исходное заявление OP

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

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

Кстати, для двух вышеуказанных запросов оптимизатор SQL-сервера не будет выполнять оптимизацию, но будет использовать план Trivila, пока общая стоимость плана меньше пороговой стоимости параллелизма.


0

Это правда, если предположить, что имена не индексируются. Однако разные данные сделают это неверным. Чтобы выяснить, какой способ сделать это, который может каждый раз отличаться, СУБД должна будет выполнить отдельный запрос подсчета для каждого столбца и сравнить числа, что будет стоить больше, чем просто пожать плечами и продолжить.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.