В запросе к базе данных SQL коррелированный подзапрос (также известный как синхронизированный подзапрос ) — это подзапрос (запрос, вложенный в другой запрос), который использует значения из внешнего запроса. Это может оказать существенное влияние на производительность, поскольку коррелированный подзапрос может пересчитываться каждый раз при обработке каждой строки внешнего запроса. Коррелированный подзапрос может содержать другой коррелированный подзапрос.
Вот пример типичного коррелированного подзапроса. В этом примере цель — найти всех сотрудников, чья зарплата выше средней по их отделу.
SELECT employee_number , name FROM employees emp WHERE salary > ( SELECT AVG ( salary ) FROM employees WHERE department = emp . department );
В приведенном выше запросе внешний запрос:
ВЫБЕРИТЕ номер_сотрудника , имя ИЗ сотрудников emp ГДЕ зарплата > ...
и внутренний запрос (коррелированный подзапрос) —
ВЫБЕРИТЕ СРЕДНЮЮ ( зарплату ) ИЗ сотрудников , ГДЕ отдел = emp . отдел
В приведенном выше вложенном запросе внутренний запрос должен быть повторно выполнен для каждого сотрудника. (Достаточно умная реализация может кэшировать результат внутреннего запроса по каждому отделу, но даже в лучшем случае внутренний запрос должен быть выполнен один раз для каждого отдела.)
Коррелированные подзапросы могут появляться в других местах, помимо предложения WHERE ; например, этот запрос использует коррелированный подзапрос в предложении SELECT для печати всего списка сотрудников вместе со средней зарплатой для отдела каждого сотрудника. Опять же, поскольку подзапрос коррелирует со столбцом внешнего запроса, его необходимо выполнить повторно для каждой строки результата. [ необходима цитата ]
ВЫБРАТЬ номер_сотрудника , имя , ( ВЫБРАТЬ СРЕДНИЙ ( зарплата ) ОТ сотрудников ГДЕ отдел = emp . отдел ) КАК среднее_занятость отдела ОТ сотрудников emp
Обычно бессмысленно иметь коррелированный подзапрос в предложении FROM, поскольку таблица в предложении FROM необходима для оценки внешнего запроса, но коррелированный подзапрос в предложении FROM не может быть оценен до оценки внешнего запроса, что приводит к проблеме курицы и яйца . В частности, MariaDB указывает это как ограничение в своей документации. [1]
Однако в некоторых системах баз данных разрешено использовать коррелированные подзапросы при объединении в предложении FROM, ссылаясь на таблицы, перечисленные перед объединением, используя указанное ключевое слово, создавая ряд строк в коррелированном подзапросе и присоединяя его к таблице слева. Например, в PostgreSQL добавление ключевого слова LATERAL перед правым подзапросом [2] или в Microsoft SQL Server использование ключевого слова CROSS APPLY или OUTER APPLY вместо JOIN [3] позволяет достичь эффекта.
Обычно используемый вычислительный метод для коррелированного подзапроса заключается в его переписывании в эквивалентный плоский запрос [4] (процесс, известный как выравнивание [5] [6] [7] [8] ). Разработка алгоритма в этом направлении имеет преимущество низкой сложности. Поскольку это настраиваемый подход, существующие системы баз данных не могут выравнивать произвольные коррелированные подзапросы, следуя определенным общим правилам. Кроме того, этот подход требует больших инженерных усилий для внедрения алгоритмов выравнивания в ядро базы данных. Общий вычислительный подход заключается в непосредственном выполнении вложенного цикла путем итерации всех кортежей коррелированных столбцов из внешнего блока запроса и выполнении подзапроса столько раз, сколько кортежей внешнего цикла. [9] Этот простой подход имеет преимущество универсальности, поскольку на него не влияет тип коррелированных операторов или структур подзапросов. Однако он имеет высокую вычислительную сложность. Подход с ускорением на базе графического процессора используется для значительного повышения производительности вложенного метода высокой алгоритмической сложности за счет использования массового параллелизма и локальности памяти устройства на графическом процессоре [10] , что позволяет достичь цели как для проектирования и реализации программного обеспечения общего назначения, так и для высокой производительности при обработке подзапросов.
Когда подзапрос встречается в предложении FROM оператора SELECT, простейшим поведением является оценка подзапроса в переходной таблице, а затем выполнение внешнего SELECT для переходной таблицы. Такой план может быть неоптимальным, поскольку у переходной таблицы не будет никаких индексов, а внешний запрос (который, скорее всего, является соединением) будет вынужден выполнить полное сканирование таблицы в переходной таблице. Чтобы преодолеть эту проблему, SQLite пытается сгладить подзапросы в предложении FROM оператора SELECT. Это включает в себя вставку предложения FROM подзапроса в предложение FROM внешнего запроса и переписывание выражений во внешнем запросе, которые ссылаются на результирующий набор подзапроса. ...
Подзапросы предложения FROM всегда оцениваются до содержащего их запроса. В некоторых случаях оптимизатор сглаживает подзапросы предложения FROM, чтобы запрос мог выполняться более эффективно.
Операторы, включающие такие подзапросы, могут быть преобразованы в объединения только в том случае, если подзапрос не вносит никаких дубликатов в результирующий набор...
Некоторые подзапросы можно сглажены в соединения. ...