Описание оптимизации выражений WHERE
помещено в раздел, посвященный
SELECT
, потому что они главным образом используются в запросах SELECT
, но
для выражений WHERE
в операторах DELETE
и UPDATE
используются те же
способы оптимизации.
Отметим также, что данный раздел неполон. В 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
Константные выражения, используемые индексами, оцениваются только один раз.
Для таблиц
HEAP
иMyISAM
функцияCOUNT(*)
, которая вызывается для одной таблицы и не содержит предложенияWHERE
, берется непосредственно из табличной информации. Это делается также для любого выраженияNOT
NULL
, в котором используется только одна таблица.Недопустимые константные выражения выявляются на ранних этапах. MySQL быстро обнаруживает, что некоторые операторы
SELECT
неосуществимы и не возвращают строк.Выполняется слияние выражения
HAVING
сWHERE
, если не используется предложениеGROUP BY
или групповые функции (COUNT(), MIN()...
).Для каждого подчиненного связывания создается более простое предложение
WHERE
, чтобы ускорить оценкуWHERE
для каждого подчиненного связывания а также чтобы пропустить записи как можно быстрее.-
Все константные таблицы считываются в первую очередь, перед любыми другими таблицами в запросе. К константным таблицам относятся следующие:
Пустая таблица или таблица с 1 строкой.
Таблица, которая используется с выражением
WHERE
для индексаUNIQUE
, илиPRIMARY KEY
, где все части индекса используются с константными выражениями и части индекса определены какNOT NULL
.
Все эти таблицы используются как константные таблицы:
mysql> SELECT * FROM t WHERE primary_key=1; mysql> 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
.
Вот некоторые примеры очень быстрых запросов:
mysql> SELECT COUNT(*) FROM tbl_name; mysql> SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name; mysql> SELECT MAX(key_part2) FROM tbl_name -> WHERE key_part_1=constant; mysql> SELECT ... FROM tbl_name -> ORDER BY key_part1,key_part2,... LIMIT 10; mysql> 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; mysql> SELECT COUNT(*) FROM tbl_name -> WHERE key_part1=val1 AND key_part2=val2; mysql> SELECT key_part2 FROM tbl_name GROUP BY key_part1;
Следующие запросы используют индексацию, чтобы получить отсортированные строки без дополнительного прохода для сортировки:
mysql> SELECT ... FROM tbl_name -> ORDER BY key_part1,key_part2,... ; mysql> SELECT ... FROM tbl_name -> ORDER BY key_part1 DESC,key_part2 DESC,... ;