Spec-Zone.ru › MySQL 5.7

8.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
    
  • Постоянные выражения, используемые индексами, вычисляются только один раз.

  • Функция COUNT для одной таблицы без подзапросов извлекается непосредственно из информации о таблице для таблиц MyISAM и MEMORY. Это также делается для любого выражения, используемого только с одной таблицей.

  • Раннее обнаружение недопустимых константных выражений. MySQL быстро обнаруживает, что некоторые операторы SELECT невозможны и возвращают ноль строк.

  • Условие WHERE объединяется с WHERE, если вы не используете GROUP BY или агрегатные функции (COUNT, MIN и так далее).

  • Для каждой таблицы в соединении создаётся более простое условие WHERE для быстрого оценивания таблицы и пропуска строк как можно скорее.

  • Все постоянные таблицы считываются до любой другой таблицы в запросе. Постоянная таблица — это любая из следующих:

    • Пустая таблица или таблица с одной строкой.

    • Таблица, используемая с условием WHERE на PRIMARY KEY или UNIQUE индексе, где все части индекса сравниваются с константными выражениями и определены как константы.

    Все следующие таблицы используются как постоянные таблицы:

    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.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/where-optimization.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API