Почему SELECT * бывают на величины быстрее, чем SELECT foo?

28

Рассмотрим таблицу значений и хэши, например, так:

+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| val        | char(9)  | NO   |     | NULL    |                |
| val_hashed | char(50) | YES  |     | NULL    |                |
+------------+----------+------+-----+---------+----------------+

Следующий запрос завершается через 0,00 секунды:

SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;

Однако этот запрос занимает 3 минуты 17 секунд:

SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;

Я вижу, что во время выполнения запроса список процессов показывает его как статус Sorting result. Ситуация полностью воспроизводима. Обратите внимание, что существует другой процесс, выполняющий INSERTоперации над таблицей непрерывно.

Почему более конкретный запрос выполняется дольше, чем *запрос? Я всегда считал, что *следует избегать запросов специально по соображениям производительности.

dotancohen
источник
7
Первые операторы, скорее всего, используют индекс первичного ключа, idчтобы найти первую строку. Второй должен отсортировать полный результат по valстолбцу (не проиндексированному) .
a_horse_with_no_name
8
ORDER BY NUMBERСинтаксис весьма подвержен ошибкам.
USR
2
Добавление к вашему последнему комментарию в SELECT *сочетании с индексом столбца в ORDER BYзапутывает, какой столбец сортируется - еще одна причина избегать *s ...
lc.
@ lc., что ты имеешь в виду?
Пейсер
@Pacerier Я имею в виду *не является явным. Поэтому говорить «дай мне все столбцы и сортировать по третьему» примерно так же детерминировано, как и говорить «иди в супермаркет и скажи мне, сколько светофоров ты проехал»
lc.

Ответы:

33

Фраза ORDER BY 1относится к различным столбцам; в первом это будет id, во втором val. Так idкак это ключ, он будет проиндексирован, и это order byбудет тривиальный объем работы. Чтобы order by val, однако, система будет извлекать каждую строку, сортировать полную таблицу по val, а затем выбрать только одну из этих строк.

Измените оба запроса на, order by idи я думаю, что ваше время выполнения будет почти одинаковым.

Майкл Грин
источник
3
Иногда самые сложные вопросы - это те, которые просто смотрят нам в глаза. Спасибо, Майкл!
dotancohen
7

Разница в производительности в вашем запросе хорошо объяснена MG. Я собираюсь обратиться к этому:

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

select *Сам по себе не несет особых штрафных санкций, это проблематично при неправильном использовании. В запросе с одной таблицей это работает просто отлично. Теперь присоедините эту таблицу к другой с 20 столбцами, а затем добавьте объединения к 5 другим таблицам с множеством столбцов в каждой. СЕЙЧАС это проблема. Так же как и люди, которые преподают широкую ленточную помощь «никогда не делай Х», не объясняя почему.

Павел
источник
3
SELECT *может быть проблемой даже для запроса одной таблицы. Например, SELECT * FROM hashes ORDER BY val;возможно , будет выполнено полное сканирование таблицы, а затем сортировка while SELECT val FROM hashes ORDER BY val;сделает только полное сканирование индекса, а не сортировку (при условии, что для val существует индекс). Таким образом, никогда не повредит выбрать только те результаты, которые нам нужны.
ypercubeᵀᴹ
Я полагаю, вы видели это? sqlblog.com/blogs/aaron_bertrand/archive/2009/10/10/…
Макс Вернон,
@ypercube, это происходит, даже если наша select(*)используется только как под- выбор? Так как это встроенный выбор, разве MySQL не будет достаточно умен, чтобы определить фактические столбцы, которые нужно выбрать?
Pacerier
Оптимизатор @Pacerier mysql имеет разные уровни «умности», в зависимости от версии, которую вы используете. В gerneal это было довольно глупо в отношении вложенных подзапросов, так что все, что вы могли ему помочь, было хорошо.
ypercubeᵀᴹ
@ypercube, Ах, если бы он был таким же умным, как pgsql.
Pacerier