20.2.24

Оператор распараллеливания (Exchange)

По материалам статьи Craig Freedman: The Parallelism Operator (aka Exchange)


Перевод Ирины Наумовой.

Как я уже писал в статье Введение в распараллеливание исполнения запроса , итератор параллелизма (или обмена - Exchange operator) фактически привносит в процесс выполнения запроса возможность распараллеливания задачи. Оптимизатор помещает оператор обмена в том месте, где происходит разделение на несколько потоков, и оператор обмена перемещает строки между потоками.

Итератор обмена – на самом деле это два итератора

Итератор обмена в действительности является двумя итераторами: производитель и потребитель (этим он отличается от всех других итераторов). Мы размещаем производителя в корень поддерева запроса (его часто называют ветвлением). Производитель считывает строки на входе своего поддерева, транслирует эти строки в пакеты, и направляет пакеты соответствующим потребителям. Потребитель размещается в «листе» следующего поддерева запроса. Потребитель принимает пакеты от своего производителя, извлекает из этих пакетов строки, и возвращает строки родительскому итератору. Например, оператор Repartition Streams, выполняющийся со степенью параллелизма (DOP) равной двойке, будет состоять из двух производителей и двух потребителей:

Обратите внимание, что, в то время как поток данных между большинством итераторов основывается на принципе «тяни» (итераторы вызывают GetRow для своих «детишек», когда готовы к обработке другой строки), поток данных оператора обмена между производителем и потребителем основан на принципе «толкай». То есть производитель заполняет пакет строками и «выталкивает» его потребителю. Эта модель позволяет потокам производителя и потребителя выполняться независимо друг от друга (тут мы имеем такое управление потоком данных, которое не позволит быстрому производителю затопить медленного потребителя большим количеством пакетов).

Сколько существует разных типов обмена?

Оператор обмена может быть классифицирован тремя различными способами.

Во-первых, мы можем классифицировать оператор обмена, основываясь на количестве потоков потребителя и/или производителя:

Тип

Количество потоков производителя

Количество потоков потребителя

Gather Streams

DOP

1

Repartition Streams

DOP

DOP

Distribute Streams

1

DOP

Оператор Gather Streams часто называют «началом распараллеливания» итератора обмена: т.е. те операторы, которые расположены в плане выше него, выполняются последовательно, а те операторы, которые ниже него, выполняются параллельно. Корнем итератора обмена любого параллельного плана всегда является оператор Gather Streams, так как результаты любого плана запроса должны, в конечном счете, собраться в один поток, который будет возвращен клиенту. Оператор Distribute Streams часто называют «завершением распараллеливания» обмена. Это противоположность предыдущему оператору: те операторы, которые выше Distribute Streams, выполняются параллельно, в то время как те операторы, которые ниже него, работают последовательно.

Во-вторых, мы можем классифицировать оператор обмена между потоками, основываясь на том, как перенаправляются строки от производителя потребителю. Обращаем Ваше внимание на свойство «Тип секционирования (partitioning type)» оператора обмена потоков. Тип секционирования имеет смысл только для оператора Repartition Streams или оператора Distribute Streams, когда у оператора Gather Streams существует только один маршрут для строк: в направлении единственного потока потребителя. SQL Сервер поддерживает следующие типы секционирования:

Тип секционирования

Описание

Broadcast

Посылает все строки всем потокам потребителя.

Round Robin

Последовательно посылает каждый пакет строк следующему потребителю.

Hash

Определяет куда посылать каждую строку на основании оценки хэш-функции для одной или более колонки в строке.

Round Robin

Range

Demand

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

В-третьих, мы можем классифицировать обмен как слияние (или сохранение порядка сортировки) и без слияния (или сохранение отсутствия упорядочивания). Потребителю при обмене слиянием гарантируется, что строки от нескольких производителей будут возвращены в заданном порядке сортировки (строки должны быть в этом порядке сортировки уже у производителя; обмен слиянием ничего не сортирует). Обмен слиянием имеет смысл только для Gather Streams или Repartition Streams; у оператора Distribute Streams только один производитель, таким образом, для него возможен только один поток строк, и нечего объединять для потребителей.

План исполнения запроса

SQL Server показывает все перечисленные выше свойства в плане исполнения запроса (в графическом, текстовом и XML представлении).

Если посмотреть на графическое представление плана исполнения запроса, там сразу видно, какие операторы распараллеливаются (то есть, какие операторы окажутся между стартовым и финишным операторами обмена), это можно узнать по небольшому символу параллелизма, дорисованному к значку оператора:

В моей следующей статье о параллелизме, я приступлю к исследованию некоторых параллельных планов исполнения запросов, и продемонстрирую несколько способов использования операторов обмена.

Комментариев нет:

Отправить комментарий