Опубликовано: 21.05.2017
Теперь, когда дерево разбора тщательно проверено, наступает очередь оптимизатора, который превращает его в план выполнения запроса. Часто существует множество способов выполнить запрос, и все они дают один и тот же результат. Задача оптимизатора - выбрать лучший из них.
В MySQL используется стоимостный оптимизатор, пытающийся предсказать стоимость различных планов выполнения и выбрать из них наиболее дешевый. В качестве единицы стоимости принимаются затраты на считывание случайной страницы данных размером 4 Кбайт. Чтобы узнать, как оптимизатор оценил запрос, выполните этот запрос, а затем посмотрите на сеансовую переменную Last_query_cost:
mysql> SELECT SQL_NO_CACHE COUNT(*) FROM sakila.film_actor;
+----------+
| count(*)
+----------+
| 5462
+----------+
mysql> SHOW STATUS LIKE ‘last_query_cost’;
+-----------------+-------------+
| Variable_name | Value
+-----------------+-------------+
| Last_query_cost | 1040.599000 |
+-----------------+-------------+
Этот результат означает, что согласно оценке оптимизатора для выполнения запроса потребуется выполнить примерно 1040 случайных чтений страниц данных. Оценка вычисляется на основе различной статистической информации: количество страниц в таблице или в индексе, кардинальность (количество различных значений) индекса, длина строк и ключей, распределение ключей. Оптимизатор не учитывает влияния кэширования - предполагается, что любое чтение сводится к операции дискового ввода/вывода.
Не всегда оптимизатор выбирает наилучший план, и тому есть много причин.
• Некорректная статистика. Сервер получает статистическую информацию от подсистемы хранения, и тут есть масса вариантов: от абсолютно верных до не имеющих ничего общего с действительностью. Например, подсистема хранения InnoDB не ведет точную статистику количества строк в таблице, так уж устроена архитектура многовер-сионного управления конкурентным доступом (MVCC).