DeepEdit!

Программирование баз данных на Oracle, техническая документация, литература, статьи и публикации

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Распределение записей

Одна из замечательных особенностей параллельных табличных функций заключается в том, что вы можете дать указания Oracle, как следует распределять записи между параллельными экземплярами функции. Можно указать две различные характеристики, влияющие на распределение. Это, во-первых, секционирование {partitioning), на основании которого Oracle решает, какие записи какому экземпляру функции направить. И, во-вторых, организация потока (streaming), определяющая порядок вывода выделенных экземпляру функции строк. Ниже для каждой из характеристик перечислены возможные варианты.
Секционирование
Записи могут быть разделены по диапазонам значений одного или нескольких столбцов, по рассчитанным для одного или нескольких столбцов кэш-значениям или просто по усмотрению Oracle. Предложение PARTITION BY указывает определенный способ секционирования для табличной функции, как показано в последующих примерах.
Организация потока
Записи могут быть упорядочены или сгруппированы по значениям определенных столбцов. В нижеследующих примерах будет показано использование ключевых слов ORDER и CLUSTER для организации выходного потока табличной функции.
Назначение и взаимодействие всех этих компонентов мы рассмотрим на примере разработки функции подсчета транзакций по учетным записям.
Произвольное секционирование (PARTITION BY ANY)
Для начала создадим функцию и заставим сервер Oracle распараллелить ее, оставив секционирование записей на его усмотрение. Предложение PARALLEL_ENABLE в заголовке функции сообщает Oracle, что код этой функции написан в расчете на параллельное выполнение, и использование этой возможности весьма желательно. Параметр PARTITION BY ANY в этом примере указывает, что записи, возвращаемые курсором типа REF CURSOR, должны быть секционированы случайным образом в том порядке, какой Oracle сочтет наиболее подходящим для имеющихся PQ-серверов. Другими словами, в данном примере PQ-серверы используются только для повышения производительности.


При выполнении этой функции используется оператор SELECT, получающий в качестве параметра оператор SELECT. Не могу не повторить еще раз!

Результат будет случайным и непредсказуемым, так как функция рассчитывает на получение записей, отсортированных по региону, но фактически распределение записей оставлено на усмотрение Oracle. Поэтому параметр PARTITION BY ANY не поможет этой функции. (Хотя позволяет получить неверный результат очень быстро!)
Секционирование по диапазону (PARTITION BY RANGE)
Для полного использования преимуществ параллельной обработки надо заставить Oracle отправлять все записи одного региона одному и тому же экземпляру функции. Например, если параллельно выполняются три экземпляра функции, то все записи региона 7 должны попасть в экземпляр 1, 2 или 3. Такой способ указывается с помощью предложения RANGE, как показано в новом заголовке функции:

Обратите внимание, что здесь для параметра REF CURSOR использована строгая типизация. То есть Oracle для корректного разделения записей должен заранее знать их структуру. Наш пакет ref_cursors содержит единственную строку:


6
96
7
97
8
98
9
99
6
414
7
423
8
432
9
441
1
369
10
450
2
378
3
387
4
396
5
405
1
91
2
92
3
93
4
94
5
95
10
100
20 rows selected

Упорядочение потока (ORDER)

Получилось пока не совсем то, что нужно. Проблема в том, что хотя записи распределяются между экземплярами соответственно региону, они не сортируются в пределах каждого экземпляра функции. Например, все записи 6-го региона отправляются одному экземпляру функции, но туда же попадают записи других регионов, что приводит к ошибкам в расчете итогов по региону 6. Надо сообщить Oracle, что записи должны сортироваться по региону еще и в каждом из экземпляров функции. Это делается с помощью предложения ORDER, как показано ниже.



AREA
AMT
1
460
10
550
2
470
3
480
4
490
5
500
6
510
7
520
8
530
9
540



Есть успех! Теперь итоговые значения верны, так как полученные курсором записи были разделены между параллельными экземплярами функции в соответствии с регионом и отсортированы в каждом из них по региону, как показано на рис. 3.2.

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









jAntivirus