Оптимизация SQL — анализ планов выполнения SQL с объяснением

MySQL

Иногда мы сталкиваемся с такими вещами: проект в сети, все идет хорошо, просто ждешь приемки продукта домой и ложишься спать, а продукт вдруг приходит к тебе:

Продукт: Почему главная страница загружается так медленно?

Разработка: Объем данных слишком велик, нет возможности

Продукт: Нет, должен быть оптимизирован

Разработка: ....

В этом случае велика вероятность того, что sql имеет медленный запрос.В это время нам нужно вытащить запрос sql для оптимизации и оптимизации, затем нам нужно использовать команду объяснения, которая будет упомянута в этой статье.

Цель этой статьи

  1. Помогите всем понять, объясните, когда вы столкнетесь с вышеуказанными проблемами, вы можете прийти сюда, чтобы проверить значение каждого поля в плане выполнения.
  2. Может быстро найти проблему на основе плана выполнения медленного запроса
  3. Предоставление общих причин проблем и решений

что может объяснить

Прежде чем понять объяснение, вы можете взглянуть на общую схему логической архитектуры службы mysql, чтобы получить общее представление о ней.

explain

Как видно из рисунка, нашему sql в основном нужно пройти следующие шаги при запросе:

  1. установить соединение с mysql
  2. Запросите, существует ли кеш, и если да, верните результат напрямую.
  3. Парсер, в основном для разбора sql
  4. Оптимизатор запросов в основном выполняет различные оптимизации SQL, включая переписывание запросов, определение порядка чтения таблиц и выбор соответствующих индексов. . и сгенерировать план выполнения
  5. Перейти к результатам запроса механизма хранения

И мы используем объяснение, чтобы перейти к оптимизатору запросов, чтобы запросить план выполнения.

объяснить объяснение поля

Посмотрите на простой план выполнения

explain select * from t_user where id = 1;

执行计划1

Мы видим, что план выполнения будет отображать связанные поля 12. Ниже мы объясним основные поля и общие значения этих полей:

id

Значение: это набор чисел, указывающий порядок, в котором предложение select или таблица операций выполняются в запросе.

правило:

  1. Если идентификатор не совпадает, чем больше значение идентификатора, тем быстрее выполнение
  2. Один и тот же идентификатор выполняется в порядке сверху вниз

select_type

Общие значения и описания следующие

ценность описывать
SIMPLE Простые операторы SELECT (за исключением операций UNION или операций подзапросов)
PRIMARY Самый внешний SELECT в запросе (например, если две таблицы — UNION или есть подзапрос, операция внешней таблицы — PRIMARY, а операция внутреннего слоя — UNION)
UNION В операции UNION внутренний SELECT в запросе, то есть SELECT по объединению
SUBQUERY SELECT в подзапросе
DERIVED Представляет запрос Select, содержащийся в предложении From.
UNION RESULT Результат объединения, в настоящее время id равен NULL

table

Задействованные таблицы

тип (важно)

Этот столбец очень важен, он показывает, какой тип соединения используется, используется индекс или нет, Общие значения от лучшего к худшему следующие: система> const> eq_ref> ссылка> диапазон> индекс> все

Описание каждого значения выглядит следующим образом.

ценность описывать
system В таблице есть только одна строка, принадлежащая движку MyISAM.
const Постоянное соединение, таблица имеет не более одной совпадающей строки, обычно используемой для сравнения первичного ключа или уникального индекса, например:
select * from t_user where id = 1;
eq_ref Когда таблица связана с запросом, для каждой строки в первой таблице ей соответствует только одна строка во второй таблице.
(1) запрос на присоединение
(2) Удар по первичному ключу или ненулевому уникальному индексу
ref Используется только крайний левый префикс индекса или используемый индекс не является уникальным индексом, индексом не с первичным ключом.
range между, внутри, > и т. д. являются типичными запросами диапазона
index Все данные в индексе должны быть просканированы, например:
select count(*) from t_user;
all полное сканирование таблицы

possible_keys

Указывает возможные индексы

key

Указывает последний используемый ключ

ref

Показывает, какой столбец индекса используется, иногда константа: указывает, какой столбец или константа используется для поиска значения в индексированном столбце.

rows

Количество строк в результирующем наборе оценивается, что означает, что MySQL оценивает количество строк, которые необходимо прочитать, чтобы найти требуемые записи, на основе статистики таблицы и выбора индекса.В принципе, чем меньше строк, тем лучше.

filtered

Количество строк в результате запроса в процентах от указанных выше строк.

Дополнительно (важно)

Этот столбец также очень важен, в основном он показывает описание дополнительной информации, которая может дать нам дополнительные сведения для понимания плана выполнения.

Общие значения и описания следующие

ценность описывать
Using filesort Когда порядок по не может использовать индекс для завершения сортировки, оптимизатор должен выбрать подходящий алгоритм для сортировки из памяти или с диска.
Using temporary Используется временная таблица
Using index Поля запроса после выборки можно получить в индексе, и нет необходимости возвращаться в таблицу, то есть так называемый покрывающий индекс, который имеет хорошую производительность запросов.
Using index condition ICP (нажатие условия индекса) было введено после mysql5.6.
Using where Фильтры сервера Mysql после извлечения строки механизмом хранения

Принцип оптимизации

Обычно существуют следующие принципы оптимизации:

  1. Пусть основной оператор запроса использует соответствующий индекс, тип ALL (полное сканирование таблицы) требует особого внимания, и в то же время установите соответствующий индекс, чтобы уменьшить количество возможных_ключей.

  2. Тип желательно должен достигать уровня ref

  3. Использование временных файлов и использование файловой сортировки в столбце «Дополнительно» необходимо удалить.

Идеи оптимизации

В соответствии с упомянутыми выше принципами оптимизации предлагаются следующие идеи оптимизации.

Для принципов оптимизации 1, 2

Вышеупомянутые пункты 1 и 2 на самом деле могут быть достигнуты путем оптимизации индекса, и чтобы индекс, который мы строим, был оптимальным, нам нужно следовать принципу: принцип индекса Samsung.

Простое описание

☆: Чем больше столбцов индекса соответствуют условию после where, тем меньше данных будет просканировано.

Например, комбинированный индекс (a, b, c), лучше всего использовать три столбца a, b, c в индексе одновременно, после где

☆: Избегайте повторной сортировки

Проще говоря, поле сортировки должно максимально использовать поле индекса, потому что индекс сортируется по умолчанию, а сортировка по полю индекса позволяет избежать повторной сортировки.

☆: Строка индекса содержит все столбцы в операторе запроса, то есть покрывающий индекс

Исходя из этого, мы должны использовать меньше select* для запроса, чтобы увеличить возможность покрытия индексов.

Если ваш индекс может собрать все вышеперечисленные три звезды, это означает, что ваш индекс является лучшим индексом!

Для принципа оптимизации 3

Мы создаем следующую таблицу и вставляем некоторые данные

пользовательская таблица

CREATE TABLE `t_user`  (
  `id` bigint(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `group_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `idx_name`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1240277101395107842 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

Групповая таблица

CREATE TABLE `t_group`  (
  `id` bigint(20) NOT NULL,
  `group_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

Using filesort

  1. Поле order by не находится в состоянии where

    Появится следующий sql. Использование файлов

    select * from t_user where group_id = 2 and age = 32 order by name;
    

    执行计划

    Но следующий sql не будет

    select * from t_user where group_id = 2 and age = 32 order by group_id ;
    

    执行计划

  2. Составной индекс по столбцам

    Пример: создайте индекс (имя, возраст, group_id) для таблицы t_user

    Появится следующая сортировка sql. Использование файлов

    select * from t_user where name= '李A' order by group_id;
    

    执行计划

    Но следующее не будет

    select * from t_user where name = '李A' order by age;
    

    执行计划

    Поскольку первый порядок запросов пропускает возраст и использует group_id напрямую, удалите индекс (имя, возраст, group_id);

  3. Так как первый шаг группировки сортируется по умолчанию, когда поля группировки удовлетворяют указанным выше условиям, также появится сообщение Использование файловой сортировки.Вы можете добавить нулевой порядок после группировки, чтобы отменить сортировку.

Using temporary

Внешний вид временных таблиц сильно влияет на производительность, в основном в следующих ситуациях

  1. Поле группировки не находится за условием where, а группировка по полю не является окончательным используемым индексом, причина в чем-то аналогична приведенной выше сортировке файлов.

    Появится следующий sql. Использование временного

    select * from t_user where group_id = 2 and name= '李A' group by age;
    

    执行计划

    Но следующий sql не будет

    select * from t_user where name = '李A' and age = 21 group by age;
    

    Вывод: где какие поля, просто сгруппируйте по каким полям

  2. При объединении таблиц столбец порядка отсутствует в таблице драйверов.

    Следующий sql создаст временную таблицу

    explain select * from t_user t1 left join t_group t2 on t1.group_id = t2.id order by t2.id;
    

    执行计划

    Потому что, когда t1 и t2 соединены, t1 является ведущей таблицей, но при сортировке используются поля ведомой таблицы t2. Если изменить сортировку полей t1, временной таблицы не будет, поэтому здесь нет примера.

    Вывод: При подключении запросов поле сортировки использует поле таблицы драйвера

  3. Когда предложения order by и group by различны

    explain select * from t_user group by group_id order by `name`;
    

    执行计划

    В этом случае можно использовать только одно и то же поле для группировки и сортировки, иначе не избежать

  4. Когда отдельный запрос и порядок добавления

    explain select DISTINCT(`name`) from t_user order by age;
    

    执行计划

    Эта ситуация иногда неизбежна, и мы можем только попытаться использовать один и тот же индекс для отдельного поля и порядок по полю. Также бывают ситуации, в которых будут появляться временные таблицы: подзапросы и объединения в from, и я не буду приводить здесь примеры по одному.

Суммировать

Оптимизация SQL уже является одним из внутренних навыков нашей внутренней разработки. Изучая структуру и идеи дизайна, не забывайте закладывать прочную основу. Надеюсь, вы сможете что-то получить.