How to Read EXPLAIN for SELECT in MySQL Without Hasty Conclusions
First look at the query plan: selected indexes, row estimates, and access order. We explain why EXPLAIN ANALYZE requires a separate solution.

In this article
Страница каталога работает медленно, и подозрение падает на SQL. План запроса помогает понять, как оптимизатор собирается получать данные. Но он не является автоматическим диагнозом: оценка числа строк и выбранный индекс требуют контекста, а реальная задержка зависит ещё и от нагрузки, данных и ожиданий.
Начните с известного простого запроса
Пример предназначен для MySQL 8.x. Используйте тестовую копию с репрезентативными данными и аккаунт с необходимыми правами чтения. Таблица products, поля id и active в примере условные: замените их на объекты своей схемы.
EXPLAIN SELECT id FROM products WHERE active = 1 LIMIT 20;
Не выполняйте пример буквально, если такой таблицы нет. Для анализа проблемы нужен реальный запрос приложения с понятными параметрами. Сложные выражения и вызываемые функции сначала изучают отдельно: чтение плана не следует считать универсальной гарантией отсутствия побочных эффектов для произвольного SQL.
Разберите способ доступа
В традиционном выводе обратите внимание на таблицу, тип доступа, возможные индексы, выбранный индекс и оценку строк. Поле possible_keys не означает, что все перечисленные индексы использованы. Поле key описывает фактически выбранный вариант в этом плане.
Оценка rows — не точный счётчик прочитанных строк реального выполнения. Статистика и распределение данных влияют на ожидания оптимизатора. Поэтому сравнивайте планы на данных, похожих на рабочие, а не только на пустой тестовой таблице.
Полный просмотр таблицы не всегда ошибка
Для маленькой таблицы или запроса, который выбирает большую часть данных, последовательный просмотр может быть разумным. Наличие индекса тоже не гарантирует быстрый ответ: индекс может отбирать слишком много записей или не соответствовать условиям.
Пример: фильтр по признаку, который установлен почти у всех товаров, имеет низкую избирательность. Добавление индекса только на этот признак не обязано помочь. Нужно учитывать весь запрос, сортировку, соединения таблиц и действительное распределение значений.
Не путайте EXPLAIN и EXPLAIN ANALYZE
EXPLAIN ANALYZE действительно выполняет запрос и показывает измеренные сведения. На тяжёлом запросе это создаёт реальную нагрузку. Не добавляйте этот режим на рабочем сервере как безобидное расширение команды просмотра плана.
Если нужны фактические измерения, выберите подходящую среду и ограничения вместе с администратором. Даже обычный SELECT может читать большой объём, конкурировать за ресурсы и удерживать нужные приложению объекты. В этой инструкции фактический прогон тяжёлого запроса не требуется.
Сравнивайте одно изменение за раз
Сохраните исходный запрос, параметры, версию сервера и план. После изменения индекса или SQL повторите анализ на сопоставимых данных. Затем отдельно измерьте время выполнения и влияние на другие операции. Индекс ускоряет одни чтения, но требует места и обслуживания при записи.
Не объявляйте оптимизацию завершённой только потому, что в плане появился индекс. Нужен результат для пользовательского сценария: быстрее ли открывается каталог, уменьшилась ли нагрузка и сохранилась ли корректность выборки. План помогает объяснить решение, но не заменяет проверку самого приложения.
The catalog page is slow, and SQL is the prime suspect. The query plan helps understand how the optimizer intends to retrieve data. However, it is not an automatic diagnosis: row estimates and the selected index require context, and actual latency also depends on load, data, and expectations.
Start with a known simple query
This example is intended for MySQL 8.x. Use a test copy with representative data and an account with the necessary read permissions. The table products, fields id and active in the example are conditional: replace them with objects from your own schema.
EXPLAIN SELECT id FROM products WHERE active = 1 LIMIT 20;
Do not run the example literally if such a table does not exist. To analyze the problem, you need a real application query with clear parameters. Complex expressions and called functions should be studied separately first: reading the plan should not be considered a universal guarantee of no side effects for arbitrary SQL.
Analyze the access method
In traditional output, pay attention to the table, access type, possible indexes, the selected index, and the row estimate. The field possible_keys does not mean that all listed indexes were used. The field key describes the actually selected option in this plan.
The estimate rows is not an exact count of rows read during actual execution. Statistics and data distribution affect the optimizer's expectations. Therefore, compare plans on data similar to production, not just on an empty test table.
A full table scan is not always an error
For a small table or a query that selects most of the data, a sequential scan can be reasonable. Having an index does not guarantee a fast response: the index may retrieve too many records or fail to match the conditions.
Example: a filter on a flag that is set on almost all products has low selectivity. Adding an index only on this flag is not guaranteed to help. You must consider the entire query, sorting, table joins, and the actual distribution of values.
Do not confuse EXPLAIN with EXPLAIN ANALYZE
EXPLAIN ANALYZE actually executes the query and displays measured data. On a heavy query, this creates real load. Do not enable this mode on a production server as a harmless extension of the query plan viewer.
If you need actual measurements, choose an appropriate environment and constraints together with the administrator. Even a standard SELECT can read a large volume, compete for resources, and hold objects required by the application. This guide does not require running a heavy query in actual mode.
Compare one change at a time
Save the original query, parameters, server version, and execution plan. After changing the index or SQL, repeat the analysis on comparable data. Then measure the execution time and impact on other operations separately. An index speeds up certain reads but requires space and maintenance during writes.
Do not declare optimization complete simply because an index appears in the plan. You need results for a user scenario: does the catalog load faster, has the load decreased, and has query correctness been preserved? The plan helps explain the decision, but it does not replace testing the application itself.

Discussion0
Share your experience and ask questions. Comments without links appear after editorial review.
No comments yet. Start the discussion.