Подтвердить что ты не робот

Где происходит практика "существует (выберите 1 из...)"?

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

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 query, который показывает много людей, говорящих об этом. Если вы слишком ленивы, отметьте эту прямую ссылку, где один парень даже сравнивает планы выполнения, чтобы найти, что они эквивалентны.

4b9b3361

Ответ 1

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

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

Ответ 2

Как демонстрационный пример, попробуйте эти

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 - Insert, если он не существует), это не работает на SQL Server 2000, но я знаю, что это делается на SQL Server 2005 +

Ответ 3

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

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

Итак, для простого подзапроса EXISTS, например это:

SELECT col1 FROM MyTable WHERE EXISTS (SELECT * FROM Table2 WHERE MyTable.col1 = Table2.col2) * будет расширено до некоторого потенциально большого список столбцов, и тогда это будет что семантика EXISTS не требует каких-либо из этих столбцы, поэтому в основном все они могут удаляться.

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

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

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

Ответ 4

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

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