В чем разница между хэш-соединением и соединением слиянием (Oracle RDBMS)?

Каков прирост/потеря производительности между хэш-соединениями и соединениями слиянием, особенно в СУБД Oracle?


person Andrew Martinez    schedule 10.07.2009    source источник
comment
download.oracle.com/docs/cd/ B28359_01/сервер.111/b28274/   -  person Brian    schedule 11.07.2009
comment
orafaq.com/node/1446   -  person cagcowboy    schedule 11.07.2009
comment
use-the-index-luke.com/sql/join   -  person a_horse_with_no_name    schedule 16.07.2013


Ответы (2)


Соединение с сортировкой слияния выполняется путем сортировки двух соединяемых наборов данных в соответствии с ключами соединения и последующего их слияния. Слияние обходится очень дешево, но сортировка может быть непомерно дорогой, особенно если сортировка переносится на диск. Стоимость сортировки может быть снижена, если к одному из наборов данных можно получить доступ в отсортированном порядке через индекс, хотя доступ к большой части блоков таблицы через сканирование индекса также может быть очень дорогим по сравнению с полным сканированием таблицы. .

Хэш-соединение выполняется путем хэширования одного набора данных в память на основе столбцов соединения, считывания другого и проверки соответствия хэш-таблицы. Хеш-соединение очень дешевое, когда хэш-таблица может храниться полностью в памяти, при этом общая стоимость составляет немногим больше, чем стоимость чтения наборов данных. Стоимость возрастает, если хеш-таблица должна быть перенесена на диск при однопроходной сортировке, и значительно возрастает при многопроходной сортировке.

(В версиях, предшествующих 10g, внешние соединения из большой таблицы в маленькую были проблематичными с точки зрения производительности, поскольку оптимизатор не мог разрешить необходимость доступа сначала к меньшей таблице для хэш-соединения, а к большей таблице — для внешнего соединения. Следовательно, хэш-соединения в этой ситуации были недоступны).

Стоимость хэш-соединения можно уменьшить, разделив обе таблицы по ключу(ам) соединения. Это позволяет оптимизатору сделать вывод, что строки из раздела в одной таблице найдут соответствие только в определенном разделе другой таблицы, а для таблиц, имеющих n разделов, хэш-соединение выполняется как n независимых хэш-соединений. Это имеет следующие эффекты:

  1. Размер каждой хеш-таблицы уменьшается, что снижает максимальный объем требуемой памяти и потенциально устраняет необходимость в том, чтобы операция требовала временного дискового пространства.
  2. Для параллельных операций запросов объем обмена сообщениями между процессами значительно сокращается, что снижает использование ЦП и повышает производительность, поскольку каждое хэш-соединение может выполняться одной парой процессов PQ.
  3. Для непараллельных операций запроса потребность в памяти уменьшается в n раз, а первые строки проецируются из запроса раньше.

Следует отметить, что хеш-соединения можно использовать только для эквивалентных соединений, но соединения слиянием более гибкие.

В общем, если вы объединяете большие объемы данных в эквивалентном соединении, лучше использовать хеш-соединение.

Эта тема очень хорошо освещена в документации.

http://download.oracle.com/docs/cd/B28359_01/server.111/b28274/optimops.htm#i51523

Документы 12.1: https://docs.oracle.com/database/121/TGSQL/tgsql_join.htm

person David Aldridge    schedule 11.07.2009
comment
Спасибо. хеш-соединения можно использовать только для эквивалентных соединений, но соединения слиянием более гибкие. Концепции системы баз данных говорят, что оба используются только для эквивалентных и естественных соединений. Алгоритм слияния-соединения (также называемый алгоритмом сортировки-слияния-соединения) можно использовать для вычисления естественных соединений и равнозначных соединений. См. stackoverflow.com /вопросы/50987379/ - person Tim; 22.06.2018
comment
@Tim Да, вполне возможно, что это верно для PostgreSQL, но не для Oracle. Оптимизатор может выбрать соединение с сортировкой слиянием вместо хэш-соединения для объединения больших объемов данных, когда выполняется любое из следующих условий: ... Условие соединения между двумя таблицами не является соединением по эквивалентности, то есть используется условие неравенства, такое как ‹, ‹=, › или ›= ... В отличие от сортировки слияний, хеш-соединения требуют условия равенства. docs.oracle.com/ база данных/121/TGSQL/ - person David Aldridge; 23.06.2018

Я просто хочу отредактировать это для потомков, чтобы теги для оракула не были добавлены, когда я ответил на этот вопрос. Мой ответ был более применим к MS SQL.

Соединение слиянием является наилучшим из возможных, поскольку оно использует порядок, в результате чего для выполнения соединения требуется один проход по таблицам. ЕСЛИ у вас есть две таблицы (или покрывающие индексы), которые имеют одинаковый порядок, например, первичный ключ и индекс таблицы по этому ключу, тогда при выполнении этого действия произойдет соединение слиянием.

Хеш-соединение является следующим лучшим, поскольку это обычно делается, когда одна таблица имеет небольшое количество (относительно) элементов, эффективно создавая временную таблицу с хэшами для каждой строки, которая затем непрерывно просматривается для создания объединения.

В худшем случае это вложенный цикл, который имеет порядок (n * m), что означает отсутствие порядка или размера для использования, а соединение просто для каждой строки в таблице x ищет таблицу y для соединений.

person Spence    schedule 11.07.2009
comment
Если бы одно всегда было лучше другого, то другое никогда бы не использовалось, не так ли? Я думаю, что разница более сложная, чем это. - person David Aldridge; 12.07.2009
comment
Извините, если вы меня неправильно поняли. Я пытался описать типы соединений и почему соединение слиянием лучше. Проблема в том, что объединение слиянием работает только в том случае, если у вас есть порядок сортировки, а хэш-соединение более эффективно только тогда, когда в присоединяемой таблице относительно небольшое количество строк. Извините, если это было неясно в ответе. - person Spence; 12.07.2009
comment
Вложенные циклы — это, конечно, самое худшее, когда ничего другого невозможно. - person Spence; 12.07.2009
comment
Вложенные циклы не всегда являются худшими, поскольку соединения с вложенными циклами возвращают свои первые результаты очень быстро (с малой задержкой). Когда вы используете подсказку first_rows, высока вероятность того, что будет использоваться соединение с вложенным циклом, потому что подсказка указывает, что вам нужна низкая задержка. Иногда пользователь предпочитает высокую пропускную способность (например, пакетный процесс), иногда пользователь предпочитает низкую задержку (например, в интерактивном пользовательском интерфейсе). - person Theo; 13.07.2009
comment
Я полагаю, что если набор результатов мал, это справедливое замечание. - person Spence; 14.07.2009
comment
Накладные расходы тоже имеют значение. Вложенные циклы хорошо работают для небольших наборов данных, потому что они не требуют накладных расходов, а только стоимость за строку. Хеш-соединения могут иметь высокую стоимость за строку, но есть первоначальные накладные расходы на создание хеш-таблицы. - person Brandon; 11.04.2016