10.2.1.1 Оптимизация условия WHERE
В этом разделе обсуждаются оптимизации, которые можно применить к обработке условий WHERE. В примерах используются операторы SELECT, но те же оптимизации применяются к условиям WHERE в операторах DELETE и UPDATE.
Поскольку работа над оптимизатором MySQL продолжается, не все оптимизации, выполняемые MySQL, документированы здесь.
Возможно, вы захотите переписать свои запросы, чтобы сделать арифметические операции быстрее, пожертвовав при этом удобочитаемостью. Поскольку MySQL выполняет аналогичные оптимизации автоматически, вы часто можете избежать этой работы и оставить запрос в более понятной и поддерживаемой форме. Некоторые из оптимизаций, выполняемых MySQL, следующие:
-
Удаление ненужных скобок:
((a AND b) AND c OR (((a AND b) AND (c AND d)))) -> (a AND b AND c) OR (a AND b AND c AND d)
-
Сворачивание констант:
(a<b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
-
Удаление условий с константами:
(b>=5 AND b=5) OR (b=6 AND 5=5) OR (b=7 AND 5=6) -> b=5 OR b=6
Это происходит во время подготовки, а не во время фазы оптимизации, что помогает в упрощении объединений. Для получения дополнительной информации и примеров см. Раздел 10.2.1.9, «Оптимизация внешних объединений».
Постоянные выражения, используемые индексами, вычисляются только один раз.
-
Сравнения столбцов числовых типов с константными значениями проверяются и сворачиваются или удаляются для недопустимых или выходящих за пределы значений:
# CREATE TABLE t (c TINYINT UNSIGNED NOT NULL); SELECT * FROM t WHERE c < 256; -≫ SELECT * FROM t WHERE 1;
Дополнительную информацию см. в разделе 10.2.1.14, «Оптимизация сворачивания констант».
COUNT(*)по одному таблице безWHEREизвлекается непосредственно из информации о таблице для таблицMyISAMиMEMORY. Это также делается для любого выраженияNOT NULLпри использовании только с одной таблицей.Раннее обнаружение недопустимых константных выражений. MySQL быстро обнаруживает, что некоторые операторы
SELECTневозможны и не возвращают строк.HAVINGобъединяется сWHERE, если вы не используетеGROUP BYили агрегатные функции (COUNT(),MIN()и т. д.).Для каждой таблицы в объединении строится более простое
WHERE, чтобы получить быстроеWHEREвычисление для таблицы и также пропустить строки как можно скорее.-
Все постоянные таблицы считываются перед любыми другими таблицами в запросе. Постоянная таблица — это любая из следующих:
Пустая таблица или таблица с одной строкой.
Таблица, которая используется с условием
WHEREпо индексуPRIMARY KEYилиUNIQUE, где все части индекса сравниваются с константными выражениями и определены какNOT NULL.
Все следующие таблицы используются как постоянные:
SELECT * FROM t WHERE
primary_key=1; SELECT * FROM t1,t2 WHERE t1.primary_key=1 AND t2.primary_key=t1.id; Лучшая комбинация объединений для объединения таблиц находится путем перебора всех возможностей. Если все столбцы в условиях
ORDER BYиGROUP BYпроисходят из одной таблицы, эта таблица предпочтительнее при объединении.Если есть условие
ORDER BYи другое условиеGROUP BY, или еслиORDER BYилиGROUP BYсодержат столбцы из таблиц, отличных от первой таблицы в очереди объединения, создается временная таблица.Если используется модификатор
SQL_SMALL_RESULT, MySQL использует временную таблицу в памяти.Каждый индекс таблицы запрашивается, и используется лучший индекс, если оптимизатор не считает, что использование сканирования таблицы более эффективно. В одном случае сканирование использовалось на основе того, охватывал ли лучший индекс более 30% таблицы, но фиксированный процент больше не определяет выбор между использованием индекса или сканированием. Оптимизатор теперь более сложный и основывает свою оценку на дополнительных факторах, таких как размер таблицы, количество строк и размер блока ввода-вывода.
В некоторых случаях MySQL может считывать строки из индекса, даже не обращаясь к файлу данных. Если все столбцы, используемые из индекса, являются числовыми, для решения запроса используется только дерево индекса.
Перед выводом каждой строки те, которые не соответствуют условию
HAVING, пропускаются.
Некоторые примеры запросов, которые очень быстрые:
SELECT COUNT(*) FROM tbl_name;
SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
SELECT MAX(key_part2) FROM tbl_name
WHERE key_part1=constant;
SELECT ... FROM tbl_name
ORDER BY key_part1,key_part2,... LIMIT 10;
SELECT ... FROM tbl_name
ORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;
MySQL решает следующие запросы, используя только дерево индекса, предполагая, что индексированные столбцы являются числовыми:
SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
SELECT COUNT(*) FROM tbl_name
WHERE key_part1=val1 AND key_part2=val2;
SELECT MAX(key_part2) FROM tbl_name GROUP BY key_part1;
Следующие запросы используют индексацию для получения строк в отсортированном порядке без отдельного этапа сортировки:
SELECT ... FROM tbl_name
ORDER BY key_part1,key_part2,... ;
SELECT ... FROM tbl_name
ORDER BY key_part1 DESC, key_part2 DESC, ... ;
© 2025 Oracle
Licensed under the GPLv2 License.