Spec-Zone .ru
спецификации, руководства, описания, API
|
EXPLAIN
оператор предоставляет информацию о плане выполнения относительно a SELECT
оператор.
EXPLAIN
возвращает строку информации для каждой таблицы, используемой в SELECT
оператор. Это перечисляет таблицы в выводе в порядке, что MySQL считал бы их, обрабатывая оператор. MySQL
разрешает все соединения, используя метод соединения вложенного цикла. Это означает, что MySQL читает строку из
первой таблицы, и затем находит соответствующую строку во второй таблице, третьей таблице, и так далее. Когда
все таблицы обрабатываются, MySQL выводит выбранные столбцы и отслеживание в обратном порядке через табличный
список, пока таблица не находится, для которого там более соответствуют строки. Следующая строка читается из
этой таблицы, и процесс продолжается со следующей таблицей.
Когда EXTENDED
ключевое слово используется, EXPLAIN
производит дополнительную информацию, которая может быть просмотрена,
выходя a SHOW WARNINGS
оператор после EXPLAIN
оператор. EXPLAIN EXTENDED
также дисплеи filtered
столбец.
См. Раздел
8.8.3,"EXPLAIN EXTENDED
Выходной Формат".
Невозможно использовать EXTENDED
и PARTITIONS
ключевые слова вместе в том же самом EXPLAIN
оператор.
EXPLAIN
Выходные Столбцы Этот раздел описывает выходные столбцы, произведенные EXPLAIN
.
Более поздние разделы обеспечивают дополнительную информацию о type
и Extra
столбцы.
Каждая выходная строка от EXPLAIN
предоставляет информацию об одной таблице. Каждая строка содержит
значения, полученные в итоге в Таблице 8.1,"EXPLAIN
Выходные Столбцы", и описали более подробно после таблицы.
Таблица 8.1. EXPLAIN
Выходные Столбцы
Столбец | Значение |
---|---|
id
|
SELECT идентификатор |
select_type
|
SELECT ввести |
table |
Таблица для выходной строки |
partitions
|
Соответствующие разделы |
type |
Тип соединения |
possible_keys |
Возможное индексирует, чтобы выбрать |
key |
Индексирование фактически выбранный |
key_len
|
Длина выбранного ключа |
ref |
Столбцы по сравнению с индексированием |
rows |
Оценка строк, которые будут исследованы |
filtered
|
Процент строк фильтруется по табличному условию |
Extra |
Дополнительная информация |
SELECT
идентификатор. Это - порядковый номер SELECT
в пределах запроса. Значение может быть NULL
если строка обращается к результату объединения других строк. В
этом случае, table
столбец показывает значение как <union
указать, что строка обращается к
объединению строк с M
,N
>id
значения M
и N
.
Тип SELECT
, который может быть любым из показанных в следующей таблице.
select_type Значение |
Значение |
---|---|
SIMPLE |
Простой SELECT (не
использование UNION
или подзапросы)
|
PRIMARY |
Наиболее удаленный SELECT
|
UNION |
Второй или позже SELECT оператор в a UNION |
DEPENDENT UNION |
Второй или позже SELECT оператор в a UNION , зависящий от внешнего запроса
|
UNION RESULT |
Результат a UNION .
|
SUBQUERY |
Сначала SELECT в
подзапросе
|
DEPENDENT SUBQUERY |
Сначала SELECT в
подзапросе, зависящем от внешнего запроса
|
DERIVED |
Полученная таблица SELECT
(подзапрос в FROM пункт)
|
MATERIALIZED |
Осуществленный подзапрос |
UNCACHEABLE SUBQUERY |
Подзапрос, для которого результат не может кэшироваться и должен быть переоценен для каждой строки внешнего запроса |
UNCACHEABLE UNION |
Второе или более позднее, избранное в a UNION это принадлежит некэшируемому подзапросу (см.UNCACHEABLE SUBQUERY )
|
DEPENDENT
обычно показывает использование связанного подзапроса. См. Раздел 13.2.10.7, "Связанные подзапросы".
DEPENDENT SUBQUERY
оценка отличается от UNCACHEABLE
SUBQUERY
оценка. Для DEPENDENT SUBQUERY
, подзапрос
переоценивается только однажды для каждого набора различных значений переменных от его внешнего
контекста. Для UNCACHEABLE SUBQUERY
, подзапрос переоценивается для
каждой строки внешнего контекста.
Cacheability подзапросов отличается от кэширования результатов запроса в кэше запроса (который описывается в Разделе 8.9.3.1, "Как Кэш Запроса Работает"). Кэширование подзапроса происходит во время выполнения запроса, тогда как кэш запроса используется, чтобы сохранить результаты только после того, как выполнение запроса заканчивается.
Имя таблицы, к которой обращается строка вывода. Это может также быть одним из следующих значений:
<union
: Строка обращается к объединению строк с M
,N
>
id
значения M
и N
.
<derived
: Строка обращается к полученному табличному результату для строки с N
>
id
значение N
.
Полученная таблица может закончиться, например, от подзапроса в FROM
пункт.
<subquery
: Строка обращается к результату осуществленного подзапроса для строки с N
>
id
значение N
. См. Раздел 8.13.16.2,
"Оптимизируя Подзапросы с Материализацией Подзапроса".
Разделы, от которых записи были бы соответствующими запросом. Этот столбец выводится на экран только
если PARTITIONS
ключевое слово используется. Значение NULL
для неразделенных таблиц. См. Раздел
17.3.5, "Получая информацию О Разделах".
Тип соединения. Для описаний различных типов см. EXPLAIN
Типы соединения.
possible_keys
столбец указывает, который индексирует MySQL, может хотеть
из использования находить строки в этой таблице. Отметьте, что этот столбец полностью независим от
порядка таблиц как выведено на экран в выводе от EXPLAIN
. Это означает что некоторые из ключей possible_keys
не могло бы быть применимым практически со
сгенерированным табличным порядком.
Если этот столбец NULL
, там не релевантны, индексирует. В этом случае
можно быть в состоянии улучшить производительность своего запроса, исследуя WHERE
пункт, чтобы проверить, обращается ли это к некоторому столбцу или столбцам, которые были бы
подходящими для того, чтобы индексировать. Если так, создайте соответствующее, индексируют и
проверяют запрос с EXPLAIN
снова.
См. Раздел
13.1.6,"ALTER TABLE
Синтаксис".
Видеть, что индексирует таблицу, имеет, использовать SHOW INDEX FROM
. tbl_name
key
столбец указывает, что ключ (индексирует) тот MySQL, фактически
решенный, чтобы использовать. Если MySQL решает использовать один из possible_keys
индексирует, чтобы искать строки, которые индексируют, перечисляется как значение ключа.
Это возможно это key
назовет индексирование, которое не присутствует в
possible_keys
значение. Это может произойти если ни один из possible_keys
индексирует являются подходящими для того, чтобы искать
строки, но все столбцы, выбранные запросом, являются столбцами некоторого другого, индексируют.
Таким образом, именованные индексируют покрытия выбранные столбцы, так, хотя это не используется,
чтобы определить, какие строки получить, индексировать сканирование более эффективно чем
сканирование строки данных.
Для InnoDB
, вторичное устройство индексирует, мог бы покрыть выбранные
столбцы, даже если запрос также выбирает первичный ключ потому что InnoDB
хранилища значение первичного ключа с каждым вторичным
устройством индексируют. Если key
NULL
,
MySQL, найденный не, индексирует, чтобы использовать для того, чтобы выполнить запрос более
эффективно.
Вынудить MySQL использовать или проигнорировать индексирование перечисленного в possible_keys
столбец, использовать FORCE
INDEX
, USE INDEX
, или IGNORE INDEX
в Вашем запросе. См. Раздел 13.2.9.3, "Индексируйте
Синтаксис Подсказки".
Для MyISAM
таблицы, работая ANALYZE TABLE
помогает оптимизатору выбрать, лучше индексирует. Для
MyISAM
таблицы, myisamchk - анализируют, делает то же самое. См.
Раздел
13.7.2.1,"ANALYZE TABLE
Синтаксис", и Раздел
7.6,"MyISAM
Табличное Обслуживание и Восстановление
Катастрофического отказа".
key_len
столбец указывает на длину ключа что MySQL, решенный, чтобы
использовать. Длина NULL
если key
столбец
говорит NULL
. Отметьте что значение key_len
позволяет Вам определить, сколько частей ключевого MySQL
многократной части фактически использует.
ref
шоу столбца, которые столбцы или константы по сравнению с
индексированием именованного в key
столбец, чтобы выбрать строки из
таблицы.
rows
столбец указывает, что число MySQL строк полагает, что должно
исследовать, чтобы выполнить запрос.
Для InnoDB
таблицы, это
число является оценкой, и, возможно, всегда не точно.
filtered
столбец указывает на предполагаемый процент строк таблицы,
которые будут фильтроваться по табличному условию. Таким образом, rows
показывает предполагаемое число исследованных строк и rows
× filtered
/ 100
показывает число строк, к
которым присоединятся с предыдущими таблицами. Этот столбец выводится на экран, если Вы используете
EXPLAIN EXTENDED
.
Этот столбец содержит дополнительную информацию о том, как MySQL разрешает запрос. Для описаний
различных значений см. EXPLAIN
Дополнительная информация.
EXPLAIN
Типы соединенияtype
столбец EXPLAIN
вывод описывает, как присоединяются к таблицам. Следующий список описывает типы соединения, упорядоченные от
лучшего типа до худшего:
У таблицы есть только одна строка (= системная таблица). Это - особый случай const
тип соединения.
У таблицы есть самое большее одна строка соответствия, которая читается в начале запроса. Поскольку
есть только одна строка, значения от столбца в этой строке могут быть расценены как константы
остальной частью оптимизатора. const
таблицы очень быстры, потому что они только для чтения
однажды.
const
используется, когда Вы сравниваете все части a PRIMARY KEY
или UNIQUE
индексируйте к постоянным величинам. В следующих запросах, tbl_name
может использоваться в качестве a const
таблица:
SELECT * FROMtbl_name
WHEREprimary_key
=1;SELECT * FROMtbl_name
WHEREprimary_key_part1
=1 ANDprimary_key_part2
=2;
Одна строка читается из этой таблицы для каждой комбинации строк от предыдущих таблиц. Кроме system
и
const
типы,
это - самый лучший тип соединения. Это используется, когда все части индексирования используются
соединением, и индексирование является a PRIMARY KEY
или UNIQUE NOT NULL
индексировать.
eq_ref
может использоваться для индексированных столбцов, которые сравниваются, используя =
оператор. Сравнительное значение может быть константой или
выражением, которое использует столбцы от таблиц, которые читаются перед этой таблицей. В следующих
примерах MySQL может использовать eq_ref
соедините с процессом ref_table
:
SELECT * FROMref_table
,other_table
WHEREref_table
.key_column
=other_table
.column
;SELECT * FROMref_table
,other_table
WHEREref_table
.key_column_part1
=other_table
.column
ANDref_table
.key_column_part2
=1;
Все строки с соответствием индексируют значения, читаются из этой таблицы для каждой комбинации
строк от предыдущих таблиц. ref
используется, если соединение использует только крайний левый
префикс ключа или если ключ не является a PRIMARY KEY
или UNIQUE
индексируйте (другими словами, если соединение не может
выбрать единственную строку, основанную на значении ключа). Если ключ, который используется
соответствия только несколько строк, это - хороший тип соединения.
ref
может
использоваться для индексированных столбцов, которые сравниваются, используя =
или <=>
оператор. В следующих
примерах MySQL может использовать a ref
соедините с процессом ref_table
:
SELECT * FROMref_table
WHEREkey_column
=expr
;SELECT * FROMref_table
,other_table
WHEREref_table
.key_column
=other_table
.column
;SELECT * FROMref_table
,other_table
WHEREref_table
.key_column_part1
=other_table
.column
ANDref_table
.key_column_part2
=1;
Соединение выполняется, используя a FULLTEXT
индексировать.
Этот тип соединения походит ref
, но с дополнением, что MySQL делает дополнительный поиск строк,
которые содержат NULL
значения. Эта оптимизация типа соединения
используется чаще всего в разрешении подзапросов. В следующих примерах MySQL может использовать a ref_or_null
соедините с процессом ref_table
:
SELECT * FROMref_table
WHEREkey_column
=expr
ORkey_column
IS NULL;
Этот тип соединения указывает, что Индексировать оптимизация Слияния используется. В этом случае,
key
столбец в выходной строке содержит список, индексирует
используемый, и key_len
содержит список самых длинных ключевых ролей
для индексирования используемого. Для получения дополнительной информации см. Раздел
8.13.2, "Индексируйте Оптимизация Слияния".
Этот тип замены ref
для некоторых IN
подзапросы
следующей формы:
value
IN (SELECTprimary_key
FROMsingle_table
WHEREsome_expr
)
unique_subquery
только индексировать функция поиска, которая заменяет подзапрос полностью для лучшей эффективности.
Этот тип соединения подобен unique_subquery
. Это заменяет IN
подзапросы, но это работает на групповой, индексирует в подзапросах следующей формы:
value
IN (SELECTkey_column
FROMsingle_table
WHEREsome_expr
)
Только строки, которые находятся в данном диапазоне, получаются, используя индексирование, чтобы
выбрать строки. key
столбец в выходной строке указывает, которые
индексируют, используется. key_len
содержит самую длинную ключевую
роль, которая использовалась. ref
столбец NULL
для этого типа.
range
может
использоваться, когда ключевой столбец по сравнению с постоянным использованием любого из =
, <>
,
>
,
>=
, <
, <=
, IS NULL
, <=>
, BETWEEN
, или IN()
операторы:
SELECT * FROMtbl_name
WHEREkey_column
= 10;SELECT * FROMtbl_name
WHEREkey_column
BETWEEN 10 and 20;SELECT * FROMtbl_name
WHEREkey_column
IN (10,20,30);SELECT * FROMtbl_name
WHEREkey_part1
= 10 ANDkey_part2
IN (10,20,30);
index
тип соединения является тем же самым как ALL
, за исключением того, что индексировать дерево сканируется. Это
происходит два пути:
Если индексирование является покрытием, индексируют для запросов и
может использоваться, чтобы удовлетворить все данные, требуемые от таблицы, только
индексировать дерево сканируется. В этом случае, Extra
столбец
говорит Using index
. Только индексированное сканирование обычно
быстрее чем ALL
потому что размер индексирования обычно меньше
чем табличные данные.
Полное сканирование таблицы выполняется, используя чтения от
индексирования, чтобы искать, строки данных в индексируют порядок. Uses
index
не появляется в Extra
столбец.
MySQL может использовать этот тип соединения, когда запрос использует только столбцы, которые являются частью сингла, индексируют.
Полное сканирование таблицы делается для каждой комбинации строк от предыдущих таблиц. Это обычно не
хорошо, если таблица является первой таблицей, не отмеченной const
, и обычно очень
плохо во всех других случаях. Обычно, можно избежать ALL
добавлением индексирует, которые включают извлечению строки от
таблицы, основанной на постоянных величинах или значениях столбцов от более ранних таблиц.
EXPLAIN
Дополнительная информацияExtra
столбец EXPLAIN
вывод содержит дополнительную информацию о том, как MySQL разрешает запрос. Следующий список объясняет значения,
которые могут появиться в этом столбце. Если Вы хотите сделать свои запросы с такой скоростью, как возможный,
высматривать Extra
значения Using filesort
и Using temporary
.
const row not found
Для запроса такой как SELECT ... FROM
, таблица была пуста. tbl_name
Deleting all rows
Для DELETE
, некоторые механизмы хранения (такой как MyISAM
) поддерживайте метод обработчика, который удаляет все строки
таблицы простым и быстрым способом. Это Extra
значение выводится на
экран, если механизм использует эту оптимизацию.
Distinct
MySQL ищет отличные значения, таким образом, он прекращает искать больше строк для текущей комбинации строки после того, как он нашел первую строку соответствия.
FirstMatch(
tbl_name
)
Полуобъединение FirstMatch присоединяются к сокращенной стратегии, используется для tbl_name
.
Full scan on NULL key
Это происходит для подоптимизации запросов как стратегия нейтрализации, когда оптимизатор не может использовать метод доступа индексировать-поиска.
Impossible HAVING
HAVING
пункт всегда является ложью и не может выбрать строки.
Impossible WHERE
WHERE
пункт всегда является ложью и не может выбрать строки.
Impossible WHERE noticed after reading const tables
MySQL считал все const
(и system
) таблицы и уведомление, что WHERE
пункт всегда является ложью.
LooseScan(
m
..n
)
Полуобъединение стратегия LooseScan используется. m
и n
числа ключевой роли.
No matching min/max row
Никакая строка не удовлетворяет условие для запроса такой как SELECT MIN(...)
FROM ... WHERE
. condition
no matching row in const table
Для запроса с соединением была пустая таблица или таблица без строк, удовлетворяющих условие уникального индекса.
No matching rows after partition pruning
Для DELETE
или UPDATE
,
оптимизатор, найденный ничем, чтобы не удалить или обновить после сокращения раздела. Это подобно в
значении Impossible WHERE
для SELECT
операторы.
No tables used
Запрос имеет нет FROM
пункт, или имеет a FROM
DUAL
пункт.
Для INSERT
или REPLACE
операторы, EXPLAIN
дисплеи это значение, когда есть нет SELECT
часть. Например, это появляется для EXPLAIN
INSERT INTO t VALUES(10)
потому что это эквивалентно EXPLAIN INSERT
INTO t SELECT 10 FROM DUAL
.
Not exists
MySQL смог сделать a LEFT JOIN
оптимизация на запросе и не исследует
больше строк в этой таблице для предыдущей комбинации строки после того, как это находит одну
строку, которая соответствует LEFT JOIN
критерии. Вот пример типа
запроса, который может быть оптимизирован этот путь:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
Примите это t2.id
определяется как NOT
NULL
. В этом случае, сканирования MySQL t1
и ищет строки в t2
использование значений t1.id
. Если MySQL
находит соответствующую строку в t2
, это знает это t2.id
никогда не может быть NULL
, и не
сканирует через остальную часть строк в t2
у этого есть то же самое
id
значение. Другими словами, для каждой строки в t1
, MySQL должен прикончить только единственный поиск t2
, независимо от того, сколько строк фактически соответствуют в
t2
.
Range checked for each record (index map:
N
)
MySQL, найденный отрицательным результатом, индексирует, чтобы использовать, но нашел, что часть из
индексирует, мог бы использоваться после того, как значения столбцов от предыдущих таблиц известны.
Для каждой комбинации строки в предыдущих таблицах MySQL проверяет, возможно ли использовать a range
или index_merge
метод доступа, чтобы получить строки. Это не очень
быстро, но быстрее, чем выполнение соединения без индексирует вообще. Критерии применимости как
описываются в Разделе 8.13.1, "Оптимизация Диапазона",
и Раздел 8.13.2, "Индексируют Оптимизация Слияния",
за исключением того, что все значения столбцов для предыдущей таблицы известны и, как полагают,
константы.
Индексирует нумеруются, начинаясь 1, в том же самом порядке как показано SHOW INDEX
для таблицы. Индексировать значение карты N
значение битовой маски, которое указывает, который
индексирует, кандидаты. Например, значение 0x19
(двоичные 11001),
средство, которое индексирует 1, 4, и 5, рассмотрят.
Scanned
N
databases
Это указывает, сколько сканирований каталога сервер выполняет, обрабатывая запрос для INFORMATION_SCHEMA
таблицы, как описано в Разделе
8.2.4, "Оптимизируя INFORMATION_SCHEMA
Запросы". Значение
N
может быть 0, 1, или all
.
Select tables optimized away
Запрос содержавшие только агрегатные функции (MIN()
, MAX()
) это было все разрешено, используя индексирование, или COUNT(*)
для
MyISAM
, и нет GROUP BY
пункт. Оптимизатор,
определенный, что только одна строка должна быть возвращена.
Skip_open_table
, Open_frm_only
, Open_trigger_only
, Open_full_table
Эти значения указывают на открывающую файл оптимизацию, которая применяется к запросам для INFORMATION_SCHEMA
таблицы, как описано в Разделе
8.2.4, "Оптимизируя INFORMATION_SCHEMA
Запросы".
Skip_open_table
: Табличные файлы не должны
быть открыты. Информация уже стала доступной в пределах запроса, сканируя каталог базы
данных.
Open_frm_only
: Только таблица .frm
файл должен быть открытым.
Open_trigger_only
: Только таблица .TRG
файл должен быть открытым.
Open_full_table
: Неоптимизированный
информационный поиск. .frm
, .MYD
,
и .MYI
файлы должны быть открыты.
Start temporary
, End
temporary
Это указывает на использование временной таблицы для Копии полуобъединения стратегия Weedout.
unique row not found
Для запроса такой как SELECT ... FROM
, никакие строки не удовлетворяют условие
для a tbl_name
UNIQUE
индексируйте или PRIMARY KEY
на таблице.
Using filesort
MySQL должен сделать дополнительную передачу, чтобы узнать, как получить строки в сортированном
порядке. Вид делается, проходя через все строки согласно типу соединения и храня ключ сортировки и
указатель на строку для всех строк, которые соответствуют WHERE
пункт.
Ключи тогда сортируются, и строки получаются в сортированном порядке. См. Раздел
8.13.13,"ORDER BY
Оптимизация".
Using index
Информация о столбце получается от таблицы, используя только информацию в индексировать дереве, не имея необходимость делать, дополнительное стремится считать фактическую строку. Эта стратегия может использоваться, когда запрос использует только столбцы, которые являются частью сингла, индексируют.
Если Extra
столбец также говорит Using
where
, это означает, что индексирование используется, чтобы выполнить поиски значений ключа.
Без Using where
, оптимизатор может читать индексирование, чтобы
избежать читать строки данных, но не использовать его для поисков. Например, если индексирование
является покрытием, индексируют для запроса, оптимизатор может отсканировать это, не используя это
для поисков.
Для InnoDB
таблицы, у которых есть определяемый пользователем
кластерный индекс, которые индексируют, могут использоваться даже когда Using
index
отсутствует в Extra
столбец. Дело обстоит так, если
type
index
и key
PRIMARY
.
Using index condition
Таблицы читаются доступом, индексируют кортежи и тестирование их сначала, чтобы определить, считать ли полные строки таблицы. Таким образом индексируйте информацию, используется, чтобы задержать ("отталкивают") читающие полные строки таблицы, если это не необходимо. См. Раздел 8.13.4, "Индексируйте Кондайшн Пушдаун Оптимизэйшн".
Using index for group-by
Подобный Using index
табличный метод доступа, Using
index for group-by
указывает, что MySQL, найденный индексированием, которое может
использоваться, чтобы получить все столбцы a GROUP BY
или DISTINCT
запрос без любого дополнительного доступа к диску к
фактической таблице. Дополнительно, индексирование используется самым эффективным способом так,
чтобы для каждой группы, только несколько элементов индекса были считаны. Для получения
дополнительной информации см. Раздел 8.13.14,"GROUP BY
Оптимизация".
Using join buffer (Block Nested Loop)
, Using join buffer (Batched Key Access)
Таблицы от более ранних соединений читаются в частях в буфер соединения, и затем их строки
используются от буфера, чтобы выполнить соединение с текущей таблицей. (Block
Nested Loop)
указывает на использование Блочного алгоритма Вложенного цикла и (Batched Key Access)
указывает на использование алгоритма Пакетного
доступа по ключу. Таким образом, ключи от таблицы на предыдущей строке EXPLAIN
вывод будет буферизован, и соответствующие строки будут
выбраны в пакетах от таблицы, представленной строкой в который Using join
buffer
появляется.
Using MRR
Таблицы читаются, используя Многодиапазонную стратегию оптимизации Чтения. См. Раздел 8.13.11, "Многодиапазонная Оптимизация Чтения".
Using sort_union(...)
, Using
union(...)
, Using intersect(...)
Они указывают, как индексируют сканирования, объединяются для index_merge
тип соединения. См. Раздел
8.13.2, "Индексируйте Оптимизация Слияния".
Using temporary
Чтобы разрешить запрос, MySQL должен создать временную таблицу, чтобы содержать результат. Это
обычно происходит, если запрос содержит GROUP BY
и ORDER BY
пункты тот список столбцы по-другому.
Using where
A WHERE
пункт используется, чтобы ограничить который строки
соответствовать против следующей таблицы или передаться клиенту. Если Вы определенно не
намереваетесь выбрать или исследовать все строки от таблицы, у Вас может быть что-то не так в Вашем
запросе если Extra
значение не Using where
и табличный тип соединения ALL
или index
.
Using where with pushed condition
Этот элемент применяется к NDB
EXPLAIN
Выходная Интерпретация Можно получить хорошую индикацию относительно того, насколько хороший соединение, принимая продукт значений
rows
столбец EXPLAIN
вывод. Это должно сказать Вам примерно, сколько MySQL строк должен исследовать, чтобы выполнить запрос. Если Вы
ограничиваете запросы с max_join_size
системная переменная, этот продукт строки также используется,
чтобы определить который многократная таблица SELECT
операторы, чтобы выполниться и чтобы прерваться. См. Раздел
8.11.2, "Настраивая Параметры Сервера".
Следующий пример показывает, как многократно-табличное соединение может быть оптимизировано прогрессивно
основанное на информации, предоставленной EXPLAIN
.
Предположите, что Вы имеете SELECT
оператор, показанный здесь и что Вы планируете исследовать это
использование EXPLAIN
:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference, tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID, tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess, tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted, et.COUNTRY, et_1.COUNTRY, do.CUSTNAME FROM tt, et, et AS et_1, do WHERE tt.SubmitTime IS NULL AND tt.ActualPC = et.EMPLOYID AND tt.AssignedPC = et_1.EMPLOYID AND tt.ClientID = do.CUSTNMBR;
Для этого примера сделайте следующие предположения:
Сравниваемые столбцы были объявлены следующим образом.
Таблица | Столбец | Тип данных |
---|---|---|
tt |
ActualPC |
CHAR(10) |
tt |
AssignedPC |
CHAR(10) |
tt |
ClientID |
CHAR(10) |
et |
EMPLOYID |
CHAR(15) |
do |
CUSTNMBR |
CHAR(15) |
У таблиц есть следующее, индексирует.
Таблица | Индексировать |
---|---|
tt |
ActualPC |
tt |
AssignedPC |
tt |
ClientID |
et |
EMPLOYID (первичный ключ) |
do |
CUSTNMBR (первичный ключ) |
tt.ActualPC
значения не равномерно распределяются.
Первоначально, прежде, чем любая оптимизация была выполнена, EXPLAIN
оператор производит следующую информацию:
table type possible_keys key key_len ref rows Extraet ALL PRIMARY NULL NULL NULL 74do ALL PRIMARY NULL NULL NULL 2135et_1 ALL PRIMARY NULL NULL NULL 74tt ALL AssignedPC, NULL NULL NULL 3872 ClientID, ActualPC Range checked for each record (index map: 0x23)
Поскольку type
ALL
для каждой таблицы этот вывод
указывает, что MySQL генерирует Декартово произведение всех таблиц; то есть, каждая комбинация строк. Это
занимает вполне длительное время, потому что продукт числа строк в каждой таблице должен быть исследован. Для
случая под рукой, этот продукт является 74 × 2135 × 74 × 3872 = 45,268,558,720 строк. Если бы таблицы были
больше, можно только вообразить, сколько времени это взяло бы.
Одна проблема здесь состоит в том, что MySQL может использовать, индексирует на столбцах более эффективно, если
они объявляются как тот же самый тип и размер. В этом контексте, VARCHAR
и CHAR
считаются тем же самым, если они объявляются как тот же самый размер.
tt.ActualPC
объявляется как CHAR(10)
и et.EMPLOYID
CHAR(15)
, таким образом, есть
несоответствие длины.
Чтобы фиксировать эту несоизмеримость между длинами столбца, использовать ALTER TABLE
удлинить ActualPC
от 10 символов до 15
символов:
mysql> ALTER TABLE tt MODIFY ActualPC
VARCHAR(15);
Теперь tt.ActualPC
и et.EMPLOYID
оба VARCHAR(15)
. Выполнение EXPLAIN
оператор снова приводит к этому результату:
table type possible_keys key key_len ref rows Extratt ALL AssignedPC, NULL NULL NULL 3872 Using ClientID, where ActualPCdo ALL PRIMARY NULL NULL NULL 2135 Range checked for each record (index map: 0x1)et_1 ALL PRIMARY NULL NULL NULL 74 Range checked for each record (index map: 0x1)et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
Это не совершенно, но намного лучше: продукт rows
значения меньше фактором 74.
Через несколько секунд выполняется эта версия.
Второе изменение может быть сделано устранить несоответствия длины столбца для tt.AssignedPC
= et_1.EMPLOYID
и tt.ClientID = do.CUSTNMBR
сравнения:
mysql>ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
->MODIFY ClientID VARCHAR(15);
После той модификации, EXPLAIN
производит вывод, показанный здесь:
table type possible_keys key key_len ref rows Extraet ALL PRIMARY NULL NULL NULL 74tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 Using ClientID, where ActualPCet_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
В этой точке запрос оптимизируется почти так же как возможный. Остающаяся проблема состоит в том, что по
умолчанию MySQL предполагает что значения в tt.ActualPC
столбец равномерно
распределяется, и дело не в этом для tt
таблица. К счастью, легко сказать MySQL
анализировать ключевое распределение:
mysql> ANALYZE TABLE tt;
С дополнительным индексируют информацию, соединение совершенно и EXPLAIN
приводит к этому результату:
table type possible_keys key key_len ref rows Extratt ALL AssignedPC NULL NULL NULL 3872 Using ClientID, where ActualPCet eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
Отметьте что rows
столбец в выводе от
EXPLAIN
образованное предположение от оптимизатора соединения MySQL.
Проверьте, являются ли числа даже близко к истине, сравниваясь rows
продукт с
фактическим числом строк, которые возвращает запрос. Если числа очень отличаются, Вы могли бы получить лучшую
производительность при использовании STRAIGHT_JOIN
в Вашем SELECT
оператор и пытающийся перечислить таблицы в различном порядке в FROM
пункт.
Возможно в некоторых случаях выполнить операторы, которые изменяют данные когда EXPLAIN SELECT
используется с подзапросом; для получения дополнительной
информации см. Раздел 13.2.10.8, "Подзапросы в FROM
Пункт".