|
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_ и iit_ представьте таблицы во
внешних и внутренних частях запроса, и ioe_ и iie_ представьте выражения, которые обращаются к
столбцам во внешних и внутренних таблицах. 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 присутствует, никакая временная таблица индексируют,
используется для табличных чтений. Иначе, индексировать поиск используется.