Spec-Zone .ru
спецификации, руководства, описания, API
|
С MySQL 5.6.5 оптимизатор использует стратегии полуобъединения улучшить выполнение подзапроса, как описано в этом разделе.
Для внутреннего объединения между двумя таблицами соединение возвращает строку из одной таблицы так много раз,
как есть соответствия в другой таблице. Но для некоторых вопросов, единственная информация, которая - вопросы,
есть ли соответствие, не число соответствий. Предположите, что есть названные таблицы class
и roster
те классы списка в программе курса и списках class (студенты
зарегистрировались в каждом class), соответственно. Чтобы перечислить классы, которым фактически
зарегистрировали студентов, Вы могли использовать это соединение:
SELECT class.class_num, class.class_nameFROM class INNER JOIN rosterWHERE class.class_num = roster.class_num;
Однако, результат перечисляет каждый class однажды для каждого зарегистрированного студента. Для вопроса, который задают, это - ненужное дублирование информации.
Принятие этого class_num
первичный ключ в class
таблица, двойное подавление могло быть достигнуто при использовании SELECT DISTINCT
, но это неэффективно, чтобы генерировать все строки
соответствия сначала только, чтобы устранить копии позже.
Тот же самый бездвойной результат может быть получен при использовании подзапроса:
SELECT class_num, class_nameFROM classWHERE class_num IN (SELECT class_num FROM roster);
Здесь, оптимизатор может распознать что IN
пункт требует, чтобы подзапрос возвратил
только один экземпляр каждого числа class от roster
таблица. В этом случае запрос
может быть выполнен как полуобъединение — то есть, работа, которая возвращает только
один экземпляр каждой строки в class
это является соответствующим строками в roster
.
Перед MySQL 5.6.6 внешняя спецификация запроса была ограничена простыми сканированиями таблицы или внутренними объединениями, используя синтаксис запятой, и ссылки представления не были возможны. С 5.6.6, внешнее объединение и синтаксис внутреннего объединения разрешается во внешней спецификации запроса, и ограничение, что ссылки на таблицу должны быть базовыми таблицами, было снято.
В MySQL подзапрос должен удовлетворить эти критерии, которые будут обработаны как полуобъединение:
Это должно быть IN
(или =ANY
) подзапрос, который появляется на верхнем уровне WHERE
или ON
пункт, возможно как термин в AND
выражение. Например:
SELECT ...FROM ot1, ...WHERE (oe1, ...) IN (SELECT ie1, ... FROM it1, ... WHERE ...);
Здесь, ot_
и i
it_
представьте таблицы во
внешних и внутренних частях запроса, и i
oe_
и i
ie_
представьте выражения, которые обращаются к
столбцам во внешних и внутренних таблицах. i
Это не должно содержать a GROUP BY
или HAVING
пункт или агрегатные функции.
Это не должно иметь ORDER BY
с LIMIT
.
Число внешних и внутренних таблиц вместе должно быть меньше чем максимальное количество таблиц, разрешенных в соединении.
Подзапрос может быть коррелирован или некоррелированый. DISTINCT
разрешается, как
LIMIT
если ORDER BY
также используется.
Если подзапрос соответствует предыдущим критериям, MySQL преобразовывает его в полуобъединение и делает выбор на основе издержек из этих стратегий:
Преобразуйте подзапрос в соединение, или используйте табличное отступление и выполните запрос как внутреннее объединение между таблицами подзапроса и внешними таблицами. Табличное отступление вытягивает таблицу из подзапроса к внешнему запросу.
Двойной Weedout: Выполните полуобъединение, как будто это было соединение, и удалите двойные записи, используя временную таблицу.
FirstMatch: Когда сканирование внутренних таблиц для комбинаций строки и там является многократными экземплярами данной группы значения, выбирает один вместо того, чтобы возвратить их всех. Это сканирование "ярлыков" и устраняет производство ненужных строк.
LooseScan: Отсканируйте таблицу подзапроса, используя индексирование, которое позволяет единственному значению быть выбранным из группы значения каждого подзапроса.
Осуществите подзапрос во временную таблицу с индексированием и используйте временную таблицу, чтобы выполнить соединение. Индексирование используется, чтобы удалить копии. Индексирование могло бы также использоваться позже для поисков, присоединяясь к временной таблице с внешними таблицами; в противном случае таблица сканируется.
Каждая из этих стратегий кроме Двойного Weedout может быть включена или отключила использование optimizer_switch
системная переменная. semijoin
отметьте средства управления, используются ли полуобъединения. Если это устанавливается в on
,
firstmatch
, loosescan
, и materialization
флаги включают более прекрасному управлению разрешенными стратегиями полуобъединения. Эти флаги on
по умолчанию. См. Раздел
8.8.5.2, "Управляя Переключаемой Оптимизацией".
Использование стратегий полуобъединения обозначается в EXPLAIN
вывод следующим образом:
Полуобъединяемые таблицы обнаруживаются во внешнем избранном. EXPLAIN EXTENDED
плюс SHOW WARNINGS
показывает переписанный запрос, который выводит на экран
структуру полуобъединения. От этого можно понять, о котором таблицы были вытащены полуобъединения. Если
подзапрос был преобразован в полуобъединение, Вы будете видеть, что предиката подзапроса не стало и его
таблицы и WHERE
пункт был объединен во внешний список соединения запроса и
WHERE
пункт.
Использование временной таблицы для Двойного Weedout обозначается Start temporary
и End temporary
в Extra
столбец. Таблицы, которые не были вытащены и находятся в диапазоне EXPLAIN
выходные строки, покрытые Start temporary
и End
temporary
будет иметь их rowid
во временной таблице.
FirstMatch(
в tbl_name
)Extra
столбец указывает на сокращенное соединение.
LooseScan(
в m
..n
)Extra
столбец
указывает на использование стратегии LooseScan. m
и n
числа ключевой роли.
С MySQL 5.6.7 использование временной таблицы для материализации обозначается
строками с a select_type
значение MATERIALIZED
и строки с a table
значение <subquery
. N
>
Перед MySQL 5.6.7 использование временной таблицы для материализации обозначается в Extra
столбец Materialize
если единственная
таблица используется, или Start materialize
и End
materialize
если многократные таблицы используются. Если Scan
присутствует, никакая временная таблица индексируют,
используется для табличных чтений. Иначе, индексировать поиск используется.