Предложение соединения в языке структурированных запросов ( SQL ) объединяет столбцы из одной или нескольких таблиц в новую таблицу. Эта операция соответствует операции соединения в реляционной алгебре . Неформально, соединение объединяет две таблицы и помещает в одну и ту же строку записи с совпадающими полями : INNER
, LEFT OUTER
, и .RIGHT OUTER
FULL OUTER
CROSS
Чтобы объяснить типы соединений, в оставшейся части этой статьи используются следующие таблицы:
Department.DepartmentID
является первичным ключом таблицы Department
, тогда как Employee.DepartmentID
является внешним ключом .
Отметим Employee
, что в России «Вильямс» еще не приписан к отделу. Также в отдел «Маркетинг» не закреплены сотрудники.
Это операторы SQL для создания приведенных выше таблиц:
СОЗДАТЬ ТАБЛИЦУ ( _ DepartmentID INT PRIMARY KEY NOT NULL , Название отдела VARCHAR ( 20 ) );СОЗДАТЬ ТАБЛИЦУ сотрудника ( Фамилия ВАРЧАР ( 20 ), DepartmentID INT ССЫЛКИ отдела ( DepartmentID ) );ВСТАВИТЬ В отдел ЗНАЧЕНИЯ ( 31 , 'Продажи' ), ( 33 , 'Инженерное дело' ), ( 34 , 'Клерикал' ), ( 35 , «Маркетинг» ); ВСТАВИТЬ В сотрудника ЦЕННОСТИ ( «Рафферти» , 31 ), ( «Джонс» , 33 года ), ( «Гейзенберг» , 33 ), ( «Робинзон» , 34 года ), ( «Смит» , 34 года ), ( 'Уильямс' , NULL );
CROSS JOIN
возвращает декартово произведение строк из таблиц в объединении. Другими словами, он будет создавать строки, объединяющие каждую строку из первой таблицы с каждой строкой из второй таблицы. [1]
Пример явного перекрестного соединения:
ВЫБРАТЬ * ОТ сотрудника отдела CROSS JOIN ;
Пример неявного перекрестного соединения:
ВЫБРАТЬ * ИЗ сотрудника , отдела ;
Перекрестное соединение можно заменить внутренним соединением с всегда истинным условием:
SELECT * FROM сотрудника отдела INNER JOIN ON 1 = 1 ;
CROSS JOIN
сам по себе не применяет никаких предикатов для фильтрации строк из объединенной таблицы. Результаты a CROSS JOIN
можно отфильтровать с помощью WHERE
предложения, которое затем может создать эквивалент внутреннего соединения.
В стандарте SQL:2011 перекрестные соединения являются частью дополнительного пакета F401 «Расширенная объединенная таблица».
Обычное использование предназначено для проверки производительности сервера. [ почему? ]
Внутреннее соединение (или join ) требует, чтобы каждая строка в двух соединенных таблицах имела совпадающие значения столбцов, и это часто используемая операция соединения в приложениях , но ее не следует считать лучшим выбором во всех ситуациях. Внутреннее соединение создает новую таблицу результатов путем объединения значений столбцов двух таблиц (A и B) на основе предиката соединения. Запрос сравнивает каждую строку A с каждой строкой B, чтобы найти все пары строк, удовлетворяющие предикату соединения. Когда предикат соединения удовлетворяется путем сопоставления значений, отличных от NULL , значения столбцов для каждой совпавшей пары строк A и B объединяются в результирующую строку.
Результат соединения можно определить как результат сначала взятия декартова произведения (или перекрестного соединения) всех строк в таблицах (объединения каждой строки в таблице A с каждой строкой в таблице B), а затем возврата всех строк, удовлетворяющих условию предикат соединения. Реальные реализации SQL обычно используют другие подходы, такие как хеш-соединения или соединения сортировки-слияния , поскольку вычисление декартова произведения происходит медленнее и часто требует непомерно большого объема памяти для хранения.
SQL определяет два разных синтаксических способа выражения соединений: «нотацию явного соединения» и «нотацию неявного соединения». «Нотация неявного соединения» больше не считается лучшей практикой [ кто? ] , хотя системы баз данных по-прежнему поддерживают его.
«Явная нотация соединения» использует JOIN
ключевое слово, которому может предшествовать INNER
ключевое слово, чтобы указать таблицу, к которой нужно присоединиться, и ключевое ON
слово, чтобы указать предикаты для соединения, как в следующем примере:
ВЫБЕРИТЕ сотрудника . Фамилия , сотрудник . ID отдела , отдел . Имя отдела FROM сотрудника INNER JOIN отдела ON сотрудника . ID отдела = отдел . ID отдела ;
«Нотация неявного соединения» просто перечисляет таблицы для соединения в FROM
предложении оператора SELECT
, разделяя их запятыми. Таким образом, он определяет перекрестное соединение, и в этом WHERE
предложении могут применяться дополнительные предикаты-фильтры (которые действуют аналогично предикатам соединения в явной записи).
Следующий пример эквивалентен предыдущему, но на этот раз с использованием неявной записи соединения:
ВЫБЕРИТЕ сотрудника . Фамилия , сотрудник . ID отдела , отдел . Название отдела ОТ сотрудника , отдел ГДЕ сотрудник . ID отдела = отдел . ID отдела ;
Запросы, приведенные в примерах выше, объединят таблицы «Сотрудник» и «Отдел», используя столбец «DepartmentID» обеих таблиц. Если DepartmentID этих таблиц совпадают (т. е. предикат объединения удовлетворен), запрос объединит столбцы LastName , DepartmentID и DepartmentName из двух таблиц в результирующую строку. Если DepartmentID не совпадает, строка результатов не создается.
Таким образом, результатом выполнения приведенного выше запроса будет:
Сотрудник «Вильямс» и отдел «Маркетинг» не появляются в результатах выполнения запроса. Ни один из них не имеет совпадающих строк в другой соответствующей таблице: «Уильямс» не имеет связанного отдела, и ни один сотрудник не имеет идентификатора отдела 35 («Маркетинг»). В зависимости от желаемых результатов такое поведение может быть незаметной ошибкой, которой можно избежать, заменив внутреннее соединение внешним соединением.
Программистам следует проявлять особую осторожность при объединении таблиц по столбцам, которые могут содержать значения NULL , поскольку NULL никогда не будет соответствовать никакому другому значению (даже самому NULL), если только условие соединения явно не использует предикат комбинации, который сначала проверяет, соответствуют ли объединяемые столбцы NOT NULL
перед применением. остальные предикатные условия. Внутреннее соединение можно безопасно использовать только в базе данных, которая обеспечивает ссылочную целостность или где столбцы соединения гарантированно не равны NULL. Многие реляционные базы данных обработки транзакций полагаются на стандарты обновления данных атомарности, согласованности, изоляции и долговечности (ACID) для обеспечения целостности данных, поэтому внутренние соединения являются подходящим выбором. Однако базы данных транзакций обычно также имеют желательные столбцы соединения, которым разрешено иметь значение NULL. Многие реляционные базы данных и хранилища данных , предоставляющие отчеты, используют пакетные обновления извлечения, преобразования и загрузки (ETL) больших объемов , которые затрудняют или делают невозможным обеспечение соблюдения ссылочной целостности, что приводит к появлению потенциально NULL-столбцов соединения, которые автор SQL-запроса не может изменить и которые приводят к пропуску внутренних соединений. данные без указания ошибки. Выбор использования внутреннего соединения зависит от конструкции базы данных и характеристик данных. Левое внешнее соединение обычно можно заменить внутренним соединением, если столбцы соединения в одной таблице могут содержать значения NULL.
Любой столбец данных, который может иметь значение NULL (пустой), никогда не должен использоваться в качестве ссылки во внутреннем объединении, если только предполагаемым результатом не является удаление строк со значением NULL. Если столбцы соединения NULL должны быть намеренно удалены из набора результатов , внутреннее соединение может быть быстрее, чем внешнее соединение, поскольку объединение таблиц и фильтрация выполняются за один шаг. И наоборот, внутреннее соединение может привести к катастрофическому снижению производительности или даже к сбою сервера при использовании в запросе большого объема в сочетании с функциями базы данных в предложении SQL Where. [2] [3] [4] Функция в предложении SQL Where может привести к тому, что база данных будет игнорировать относительно компактные индексы таблиц. База данных может считывать и объединять выбранные столбцы из обеих таблиц, а затем уменьшать количество строк с помощью фильтра, который зависит от вычисленного значения, что приводит к относительно огромному объему неэффективной обработки.
Когда набор результатов создается путем объединения нескольких таблиц, включая основные таблицы, используемые для поиска полнотекстовых описаний кодов числовых идентификаторов (таблица поиска ), значение NULL в любом из внешних ключей может привести к удалению всей строки. из набора результатов без указания ошибки. Сложный SQL-запрос, включающий одно или несколько внутренних объединений и несколько внешних объединений, имеет одинаковый риск получения значений NULL в столбцах ссылок внутреннего соединения.
Приверженность коду SQL, содержащему внутренние соединения, предполагает, что столбцы соединения NULL не будут введены будущими изменениями, включая обновления поставщиков, изменения дизайна и массовую обработку за пределами правил проверки данных приложения, таких как преобразования данных, миграции, массовый импорт и слияния.
Кроме того, внутренние соединения можно классифицировать как эквивалентные соединения, естественные соединения или перекрестные соединения.
Эквисоединение — это особый тип соединения на основе компаратора, который использует только сравнения на равенство в предикате соединения. Использование других операторов сравнения (таких как <
) дисквалифицирует соединение как равное соединение. Запрос, показанный выше, уже предоставил пример эквивалентного соединения:
ВЫБЕРИТЕ * ИЗ сотрудника ПРИСОЕДИНЯЙТЕСЬ к отделу НА сотрудника . ID отдела = отдел . ID отдела ;
Мы можем написать equi-join, как показано ниже:
ВЫБЕРИТЕ * ИЗ сотрудника , отдела ГДЕ сотрудника . ID отдела = отдел . ID отдела ;
Если столбцы в эквиобъединении имеют одинаковые имена, SQL-92 предоставляет дополнительную сокращенную запись для выражения эквисоединения посредством конструкции USING
: [5]
ВЫБРАТЬ * ИЗ сотрудника отдела INNER JOIN USING ( DepartmentID );
Однако эта USING
конструкция представляет собой нечто большее, чем просто синтаксический сахар , поскольку набор результатов отличается от набора результатов версии с явным предикатом. В частности, любые столбцы, упомянутые в USING
списке, будут отображаться только один раз с неполным именем, а не один раз для каждой таблицы в объединении. В приведенном выше случае будет один DepartmentID
столбец и нет employee.DepartmentID
или department.DepartmentID
.
Это USING
предложение не поддерживается MS SQL Server и Sybase.
Естественное соединение является частным случаем равносоединения. Естественное соединение (⋈) — это бинарный оператор , который записывается как ( R ⋈ S ), где R и S — отношения . [6] Результатом естественного соединения является набор всех комбинаций кортежей в R и S , которые равны по своим общим именам атрибутов. В качестве примера рассмотрим таблицы «Сотрудник» и «Отдел» и их естественное соединение:
Это также можно использовать для определения состава отношений . Например, состав сотрудников и отделов — это их объединение, как показано выше, проецируемое на все атрибуты, кроме общего атрибута DeptName . В теории категорий соединение представляет собой в точности произведение расслоений .
Естественное соединение, возможно, является одним из наиболее важных операторов, поскольку оно является реляционным аналогом логического И. Обратите внимание: если одна и та же переменная появляется в каждом из двух предикатов, соединенных оператором AND, то эта переменная обозначает одно и то же, и оба появления всегда должны быть заменены одним и тем же значением. В частности, естественное соединение позволяет комбинировать отношения, связанные внешним ключом . Например, в приведенном выше примере внешний ключ, вероятно, принадлежит сотруднику . DeptName в Dept. _ DeptName , а затем естественное объединение сотрудников и отделов объединяет всех сотрудников с их отделами. Это работает, поскольку внешний ключ сохраняется между атрибутами с одинаковым именем. Если это не так, как, например, во внешнем ключе из Dept. менеджер к сотруднику . Name , то эти столбцы необходимо переименовать, прежде чем будет выполнено естественное соединение. Такое соединение иногда также называют эквивалентным соединением .
Более формально семантика естественного соединения определяется следующим образом:
где Fun — предикат , который истинен для отношения r тогда и только тогда, когда r — функция. Обычно требуется, чтобы R и S имели хотя бы один общий атрибут, но если это ограничение опущено и R и S не имеют общих атрибутов, то естественное соединение становится в точности декартовым произведением.
Естественное соединение можно смоделировать с помощью примитивов Кодда следующим образом. Пусть c 1 , ..., cm — имена атрибутов, общие для R и S , r 1 , ..., r n — имена атрибутов, уникальные для R , и пусть s 1 , ..., sk — атрибуты уникальный для С. Кроме того, предположим, что имена атрибутов x 1 , ..., x m не находятся ни в R , ни в S . На первом этапе имена общих атрибутов в S теперь можно переименовать:
Затем мы берем декартово произведение и выбираем кортежи, которые необходимо соединить:
Естественное соединение — это тип равноправного соединения, в котором предикат соединения возникает неявно путем сравнения всех столбцов в обеих таблицах, имеющих одинаковые имена столбцов в объединенных таблицах. Полученная объединенная таблица содержит только один столбец для каждой пары столбцов с одинаковыми именами. В случае, если столбцы с одинаковыми именами не найдены, результатом является перекрестное соединение .
Большинство экспертов сходятся во мнении, что NATURAL JOIN опасны, и поэтому настоятельно не рекомендуют их использовать. [7] Опасность возникает в случае непреднамеренного добавления нового столбца с таким же именем, как у другого столбца в другой таблице. Существующее естественное соединение может затем «естественным образом» использовать новый столбец для сравнений, выполняя сравнения/сопоставления с использованием других критериев (из разных столбцов), чем раньше. Таким образом, существующий запрос может давать разные результаты, даже если данные в таблицах не были изменены, а только дополнены. Использование имен столбцов для автоматического определения связей таблиц недопустимо в больших базах данных с сотнями или тысячами таблиц, где это накладывает нереальные ограничения на соглашения об именах. Реальные базы данных обычно разрабатываются с использованием данных внешнего ключа , которые не заполняются последовательно (допускаются значения NULL) из-за бизнес-правил и контекста. Обычной практикой является изменение имен столбцов схожих данных в разных таблицах, и из-за отсутствия жесткой согласованности естественные соединения относят к теоретической концепции для обсуждения.
Приведенный выше пример запроса для внутренних соединений можно выразить как естественное соединение следующим образом:
ВЫБРАТЬ * ОТ сотрудника отдела NATURAL JOIN ;
Как и в случае с явным USING
предложением, в объединенной таблице встречается только один столбец DepartmentID без квалификатора:
PostgreSQL, MySQL и Oracle поддерживают естественные соединения; Microsoft T-SQL и IBM DB2 этого не делают. Столбцы, используемые в объединении, являются неявными, поэтому код объединения не показывает, какие столбцы ожидаются, а изменение имен столбцов может изменить результаты. В стандарте SQL:2011 естественные соединения являются частью дополнительного пакета F401 «Расширенная объединенная таблица».
Во многих средах баз данных имена столбцов контролируются внешним поставщиком, а не разработчиком запросов. Естественное соединение предполагает стабильность и согласованность имен столбцов, которые могут меняться во время обновлений версий, требуемых поставщиком.
В объединенной таблице сохраняется каждая строка, даже если другой соответствующей строки не существует. Внешние соединения подразделяются на левые внешние соединения, правые внешние соединения и полные внешние соединения, в зависимости от того, какие строки таблицы сохраняются: левая, правая или обе (в данном случае левая и правая относятся к двум сторонам ключевого JOIN
слова). Как и внутренние соединения, все типы внешних соединений можно дополнительно разделить на подкатегории как эквивалентные соединения, естественные соединения, ( θ -join ) и т. д. [8]ON <predicate>
В стандартном SQL не существует неявной нотации соединения для внешних соединений.
Результат левого внешнего соединения (или просто левого соединения ) для таблиц A и B всегда содержит все строки «левой» таблицы (A), даже если условие соединения не находит ни одной подходящей строки в «правой» таблице. (Б). Это означает, что если ON
предложение соответствует 0 (нулевым) строкам в B (для данной строки в A), соединение все равно вернет строку в результате (для этой строки), но с NULL в каждом столбце из B. A left внешнее соединение возвращает все значения из внутреннего соединения, а также все значения в левой таблице, которые не соответствуют значениям в правой таблице, включая строки со значениями NULL (пустыми) в столбце ссылки.
Например, это позволяет нам найти отдел сотрудника, но по-прежнему показывает сотрудников, которые не были назначены этому отделу (в отличие от приведенного выше примера внутреннего объединения, где неназначенные сотрудники были исключены из результата).
Пример левого внешнего соединения ( OUTER
ключевое слово необязательно) с дополнительной строкой результата (по сравнению с внутренним соединением), выделенной курсивом:
ВЫБЕРИТЕ * ИЗ сотрудника СЛЕВА ВНЕШНЕГО ПРИСОЕДИНЕНИЯ отдела НА сотрудника . ID отдела = отдел . ID отдела ;
Oracle поддерживает устаревший синтаксис [9] :
ВЫБЕРИТЕ * ИЗ сотрудника , отдела ГДЕ сотрудника . ID отдела = отдел . ID отдела ( + )
Sybase поддерживает следующий синтаксис ( Microsoft SQL Server объявил этот синтаксис устаревшим с версии 2000):
ВЫБЕРИТЕ * ИЗ сотрудника , отдела ГДЕ сотрудника . ID отдела *= отдел . ID отдела
IBM Informix поддерживает синтаксис:
ВЫБЕРИТЕ * ИЗ сотрудника , ВНЕШНИЙ отдел ГДЕ сотрудник . ID отдела = отдел . ID отдела
Правое внешнее соединение (или правое соединение ) очень похоже на левое внешнее соединение, за исключением того, что таблицы обрабатываются в обратном порядке. Каждая строка из «правой» таблицы (B) появится в объединенной таблице хотя бы один раз. Если соответствующей строки из «левой» таблицы (A) не существует, NULL появится в столбцах из A для тех строк, которые не имеют совпадений в B.
Правое внешнее соединение возвращает все значения из правой таблицы и совпадающие значения из левой таблицы (NULL в случае отсутствия соответствующего предиката соединения). Например, это позволяет нам найти каждого сотрудника и его отдел, но при этом показывать отделы, в которых нет сотрудников.
Ниже приведен пример правого внешнего соединения ( OUTER
ключевое слово необязательно) с дополнительной строкой результата, выделенной курсивом:
ВЫБЕРИТЕ * ИЗ сотрудника ПРАВО ВНЕШНЕГО ПРИСОЕДИНЕНИЯ отдела НА сотрудника . ID отдела = отдел . ID отдела ;
Правое и левое внешние соединения функционально эквивалентны. Ни один из них не предоставляет никаких функций, которых нет у другого, поэтому правое и левое внешние соединения могут заменять друг друга, пока порядок таблиц переключается.
Концептуально полное внешнее соединение сочетает в себе эффект применения как левого, так и правого внешнего соединения. Если строки в полных внешних объединенных таблицах не совпадают, результирующий набор будет иметь значения NULL для каждого столбца таблицы, в котором отсутствует совпадающая строка. Для тех строк, которые совпадают, в наборе результатов будет создана одна строка (содержащая столбцы, заполненные из обеих таблиц).
Например, это позволяет нам видеть каждого сотрудника, входящего в отдел, и каждый отдел, в котором есть сотрудник, а также видеть каждого сотрудника, не входящего в состав отдела, и каждый отдел, в котором нет сотрудника.
Пример полного внешнего соединения ( OUTER
ключевое слово необязательно):
ВЫБРАТЬ * ОТ сотрудника ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ отдела НА сотрудника . ID отдела = отдел . ID отдела ;
Некоторые системы баз данных не поддерживают полную функциональность внешнего соединения напрямую, но могут имитировать ее с помощью внутреннего соединения и выбора UNION ALL «отдельных строк таблицы» из левой и правой таблиц соответственно. Тот же пример может выглядеть следующим образом:
ВЫБЕРИТЕ сотрудника . Фамилия , сотрудник . ID отдела , отдел . Название отдела , отдел . DepartmentID FROM сотрудника INNER JOIN отдела ON сотрудника . ID отдела = отдел . ID отдела СОЮЗ ВСЕХ ВЫБЕРИТЕ сотрудника . Фамилия , сотрудник . DepartmentID , cast ( NULL как varchar ( 20 ) ), cast ( NULL как целое число ) FROM сотрудника ГДЕ НЕ СУЩЕСТВУЕТ ( ВЫБРАТЬ * FROM отдел ГДЕ сотрудника .DepartmentID = Department .DepartmentID ) СОЮЗ ВСЕХ SELECT cast ( NULL как varchar ( 20 )), cast ( NULL как целое число ), отдел . Название отдела , отдел . DepartmentID ОТ отдела ГДЕ НЕ СУЩЕСТВУЕТ ( ВЫБЕРИТЕ * ОТ сотрудника ГДЕ сотрудника .DepartmentID = отдел .DepartmentID ) _ _
Другим подходом может быть UNION ALL левого внешнего соединения и правого внешнего соединения МИНУС внутреннего соединения.
Самосоединение — это присоединение таблицы к самой себе. [10]
Если бы существовало две отдельные таблицы для сотрудников и запрос, который запрашивал сотрудников в первой таблице, имеющих ту же страну, что и сотрудники во второй таблице, для поиска таблицы ответов можно было бы использовать обычную операцию соединения. Однако вся информация о сотрудниках содержится в одной большой таблице. [11]
Рассмотрим модифицированную Employee
таблицу, например следующую:
Пример запроса решения может быть следующим:
ВЫБЕРИТЕ Ф. _ Идентификатор сотрудника , Ф. Фамилии . _ _ ID сотрудника , S. Фамилия , Ф. _ Страна FROM Сотрудник F INNER JOIN Сотрудник S ON F . Страна = С. _ Страна ГДЕ Ф. _ ID сотрудника < S . ИДЕНТИФИКАТОР СОТРУДНИКА ORDER BY F . ID сотрудника , S. идентификатор сотрудника ;
В результате создается следующая таблица.
Для этого примера:
F
и S
являются псевдонимами первой и второй копий таблицы сотрудников.F.Country = S.Country
исключает создание пар между сотрудниками в разных странах. В примере вопроса речь шла только о парах сотрудников из одной страны.F.EmployeeID < S.EmployeeID
исключает пары, в которых значение EmployeeID
первого сотрудника больше или равно значению EmployeeID
второго сотрудника. Другими словами, эффект этого условия заключается в исключении дублирующих спариваний и самоспариваний. Без него была бы создана следующая менее полезная таблица (в таблице ниже отображается только часть результата «Германия»):Для ответа на исходный вопрос необходима только одна из двух средних пар, а самая верхняя и самая нижняя в этом примере вообще не представляют интереса.
Эффект внешнего соединения также можно получить, используя UNION ALL между INNER JOIN и SELECT строк в «основной» таблице, которые не удовлетворяют условию соединения. Например,
ВЫБЕРИТЕ сотрудника . Фамилия , сотрудник . ID отдела , отдел . Название отдела FROM сотрудника LEFT OUTER JOIN отдела ON сотрудника . ID отдела = отдел . ID отдела ;
также можно записать как
ВЫБЕРИТЕ сотрудника . Фамилия , сотрудник . ID отдела , отдел . Имя отдела FROM сотрудника INNER JOIN отдела ON сотрудника . ID отдела = отдел . ID отдела СОЮЗ ВСЕХ ВЫБЕРИТЕ сотрудника . Фамилия , сотрудник . DepartmentID , приведение ( NULL as varchar ( 20 ) ) ОТ сотрудника ГДЕ НЕ СУЩЕСТВУЕТ ( ВЫБЕРИТЕ * ИЗ отдела ГДЕ сотрудника.DepartmentID = Department.DepartmentID ) _ _ _
Большая часть работы в системах баз данных была направлена на эффективную реализацию соединений, поскольку реляционные системы обычно требуют соединений, но сталкиваются с трудностями при оптимизации их эффективного выполнения. Проблема возникает потому, что внутренние соединения работают как коммутативно , так и ассоциативно . На практике это означает, что пользователь просто предоставляет список таблиц для объединения и используемые условия соединения, а перед системой базы данных стоит задача определить наиболее эффективный способ выполнения операции. Оптимизатор запросов определяет, как выполнить запрос, содержащий соединения. Оптимизатор запросов имеет две основные свободы:
Многие алгоритмы соединения обрабатывают входные данные по-разному. Входные данные соединения можно называть «внешним» и «внутренним» операндами соединения или «левым» и «правым» соответственно. Например, в случае вложенных циклов система базы данных будет сканировать все внутреннее отношение на предмет каждой строки внешнего отношения.
Планы запросов, включающие соединения, можно классифицировать следующим образом: [12]
Эти имена происходят от внешнего вида плана запроса , если он нарисован в виде дерева , с внешним отношением соединения слева и внутренним отношением справа (как того требует соглашение).
Существуют три фундаментальных алгоритма выполнения операции двоичного соединения: соединение вложенного цикла , соединение сортировки-слияния и хэш-соединение . Алгоритмы оптимального соединения в худшем случае асимптотически быстрее, чем алгоритмы двоичного соединения для соединений между более чем двумя отношениями в худшем случае .
Индексы соединения — это индексы базы данных , которые облегчают обработку запросов соединения в хранилищах данных : в настоящее время (2012 г.) они доступны в реализациях Oracle [14] и Teradata . [15]
В реализации Teradata указанные столбцы, агрегатные функции для столбцов или компоненты столбцов дат из одной или нескольких таблиц указываются с использованием синтаксиса, аналогичного определению представления базы данных : в одном может быть указано до 64 столбцов/выражений столбцов. индекс соединения. При желании также можно указать столбец, определяющий первичный ключ составных данных: на параллельном оборудовании значения столбца используются для разделения содержимого индекса на несколько дисков. Когда исходные таблицы обновляются пользователями в интерактивном режиме, содержимое индекса соединения обновляется автоматически. Любой запрос, в котором предложение WHERE определяет любую комбинацию столбцов или выражений столбцов, которые являются точным подмножеством тех, которые определены в индексе соединения (так называемый «покрывающий запрос»), будет вызывать индекс соединения, а не исходные таблицы и их индексы. к ним следует обращаться во время выполнения запроса.
Реализация Oracle ограничивается использованием растровых индексов . Индекс соединения растровых изображений используется для столбцов с низкой мощностью (т. е. столбцов, содержащих менее 300 различных значений, согласно документации Oracle): он объединяет столбцы с низкой мощностью из нескольких связанных таблиц. Примером, который использует Oracle, является система инвентаризации, в которой разные поставщики поставляют разные детали. Схема имеет три связанные таблицы: две «главные таблицы» «Деталь» и « Поставщик» и «подробную таблицу» «Инвентаризация». Последняя представляет собой таблицу «многие ко многим», связывающую поставщика с деталью, и содержит наибольшее количество строк. У каждой детали есть тип детали, а каждый поставщик находится в США и имеет столбец «Штат». В США не более 60 штатов и территорий и не более 300 типов деталей. Индекс соединения растровых изображений определяется с использованием стандартного соединения трех таблиц для трех таблиц, указанных выше, и указания столбцов Part_Type и Поставщик_Состояние для индекса. Однако он определен в таблице Inventory, даже несмотря на то, что столбцы Part_Type и Поставщик_Состояние «заимствованы» у Поставщика и Детали соответственно.
Что касается Teradata, индекс соединения растровых изображений Oracle используется только для ответа на запрос, когда в предложении WHERE запроса указаны столбцы, ограниченные теми, которые включены в индекс соединения.
Некоторые системы баз данных позволяют пользователю заставить систему читать таблицы в объединении в определенном порядке. Это используется, когда оптимизатор соединения решает читать таблицы в неэффективном порядке. Например, в MySQL команда STRAIGHT_JOIN
читает таблицы точно в том порядке, который указан в запросе. [16]