Рассмотрим таблицу значений и хэши, например, так:
+------------+----------+------+-----+---------+----------------+
| 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
операции над таблицей непрерывно.
Почему более конкретный запрос выполняется дольше, чем *
запрос? Я всегда считал, что *
следует избегать запросов специально по соображениям производительности.
mysql
performance
select
dotancohen
источник
источник
id
чтобы найти первую строку. Второй должен отсортировать полный результат поval
столбцу (не проиндексированному) .ORDER BY NUMBER
Синтаксис весьма подвержен ошибкам.SELECT *
сочетании с индексом столбца вORDER BY
запутывает, какой столбец сортируется - еще одна причина избегать*
s ...*
не является явным. Поэтому говорить «дай мне все столбцы и сортировать по третьему» примерно так же детерминировано, как и говорить «иди в супермаркет и скажи мне, сколько светофоров ты проехал»Ответы:
Фраза
ORDER BY 1
относится к различным столбцам; в первом это будетid
, во второмval
. Такid
как это ключ, он будет проиндексирован, и этоorder by
будет тривиальный объем работы. Чтобыorder by val
, однако, система будет извлекать каждую строку, сортировать полную таблицу поval
, а затем выбрать только одну из этих строк.Измените оба запроса на,
order by id
и я думаю, что ваше время выполнения будет почти одинаковым.источник
Разница в производительности в вашем запросе хорошо объяснена MG. Я собираюсь обратиться к этому:
select *
Сам по себе не несет особых штрафных санкций, это проблематично при неправильном использовании. В запросе с одной таблицей это работает просто отлично. Теперь присоедините эту таблицу к другой с 20 столбцами, а затем добавьте объединения к 5 другим таблицам с множеством столбцов в каждой. СЕЙЧАС это проблема. Так же как и люди, которые преподают широкую ленточную помощь «никогда не делай Х», не объясняя почему.источник
SELECT *
может быть проблемой даже для запроса одной таблицы. Например,SELECT * FROM hashes ORDER BY val;
возможно , будет выполнено полное сканирование таблицы, а затем сортировка whileSELECT val FROM hashes ORDER BY val;
сделает только полное сканирование индекса, а не сортировку (при условии, что для val существует индекс). Таким образом, никогда не повредит выбрать только те результаты, которые нам нужны.select(*)
используется только как под- выбор? Так как это встроенный выбор, разве MySQL не будет достаточно умен, чтобы определить фактические столбцы, которые нужно выбрать?