Откуда берется практика "существует (выберите 1 из ...)"? - PullRequest
19 голосов
/ 26 мая 2011

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

SELECT * FROM tableA WHERE EXISTS (SELECT * FROM tableB WHERE tableA.x = tableB.y)
SELECT * FROM tableA WHERE EXISTS (SELECT y FROM tableB WHERE tableA.x = tableB.y)
SELECT * FROM tableA WHERE EXISTS (SELECT 1 FROM tableB WHERE tableA.x = tableB.y)
SELECT * FROM tableA WHERE EXISTS (SELECT NULL FROM tableB WHERE tableA.x = tableB.y)

Тем не менее, сегодня я столкнулся лицом к лицу с противоположным утверждением, когда на нашей внутренней встрече разработчиков было высказано мнение о том, что select 1 - это путь, и select * выбирает все (ненужные) данные, что снижает производительность.

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

Добавлено: Поскольку некоторые люди настаивают на наличии доказательств того, что это действительно ложное убеждение, здесь - запрос Google , который показывает множество людей, говорящих это так. Если вам лень, проверьте эту прямую ссылку , где один парень даже сравнивает планы выполнения, чтобы найти, что они эквивалентны.

Ответы [ 4 ]

23 голосов
/ 26 мая 2011

Основная часть вашего вопроса - «откуда появился этот миф?»

Итак, чтобы ответить на это, я думаю, что одним из первых намеков на производительность, которые люди узнают с помощью sql, является то, что select * неэффективен в большинстве ситуаций. Тот факт, что он не является неэффективным в этой конкретной ситуации, является, следовательно, несколько противоречивым. Поэтому неудивительно, что люди скептически относятся к этому. Но некоторых простых исследований или экспериментов должно быть достаточно, чтобы изгнать большинство мифов. Хотя человеческая история как бы показывает, что мифы довольно трудно изгнать.

13 голосов
/ 26 мая 2011

В качестве демонстрации попробуйте эти

SELECT * FROM tableA WHERE EXISTS (SELECT 1/0 FROM tableB WHERE tableA.x = tableB.y)
SELECT * FROM tableA WHERE EXISTS (SELECT CAST('bollocks' as int) FROM tableB WHERE tableA.x = tableB.y)

Теперь прочитайте стандарт ANSI. ANSI-92, стр. 191, случай 3a

If the <select list> "*" is simply contained in a <subquery>
          that is immediately contained in an <exists predicate>, then
          the <select list> is equivalent to a <value expression> that
          is an arbitrary <literal>.

Наконец, поведение в большинстве СУБД должно игнорировать THE * в предложении EXISTS.В соответствии с этим вопросом вчера ( Sql Server 2005 - Вставьте, если не существует ), это не работает на SQL Server 2000, но я знаю, что это работает на SQL Server 2005 +

4 голосов
/ 26 мая 2011

Для SQL Server Конор Каннингем из команды Query Optimizer объясняет, почему он обычно использует SELECT 1

QP возьмет и расширит все * в начале трубопровода и связать их с объекты (в этом случае список колонны). Затем он удалит ненужные столбцы из-за характера запрос.

Так что для простого подзапроса EXISTS, как это:

ВЫБРАТЬ col1 ИЗ MyTable, ГДЕ СУЩЕСТВУЕТ (ВЫБРАТЬ * ИЗ СТОЛБА 2 ГДЕ MyTable.col1 = Table2.col2) * будет расширен до некоторой потенциально большой список столбцов, и тогда это будет определили, что семантика EXISTS не требует ни одного из тех столбцы, так что в основном все они могут быть удаленным.

«ВЫБРАТЬ 1» позволит избежать необходимости изучить любые ненужные метаданные для этого таблица при составлении запроса.

Однако во время выполнения две формы запрос будет идентичен и будет имеют одинаковое время выполнения.

Редактировать: Однако я рассмотрел этот вопрос более подробно с момента публикации этого ответа и пришел к выводу, что SELECT 1 делает не , избегая расширения этого столбца. Полная информация здесь .

0 голосов
/ 06 июня 2014

На этот вопрос есть ответ, в котором говорится, что это была какая-то версия MS Access, которая фактически не игнорировала поле предложения SELECT. Я провел некоторую разработку Access, и я слышал, что SELECT 1 - это лучшая практика, поэтому мне кажется, что это источник «мифа».

Производительность вариантов использования SQL EXISTS

...