Расширяемость
Интерфейс BRIN имеет высокий уровень абстракции, требуя от исполнителя метода доступа только реализации семантики типа данных, к которым осуществляется доступ. Уровень BRIN сам заботится о согласовании, протоколировании и поиске в индексной структуре.
Для того чтобы метод доступа BRIN заработал, достаточно реализовать несколько пользовательских методов, которые определяют поведение суммарных значений, х ранящихся в индексе, и способ их взаимодействия с ключами сканирования. Одним словом, BRIN сочетает в себе расширяемость с универсальностью, повторным использованием кода и чистым интерфейсом.
Существует четыре метода, которые должен предоставлять класс оператора для BRIN:
BrinOpcInfo *opcInfo(Oid type_oid)
Возвращает внутреннюю информацию о сводных данных индексируемых столбцов. Возвращаемое значение должно указывать на BrinOpcInfo (в памяти palloc) со следующим определением:
typedef struct BrinOpcInfo
{
/* Number of columns stored in an index column of this opclass */
uint16 oi_nstored;
/* Opaque pointer for the opclass' private use */
void *oi_opaque;
/* Type cache entries of the stored columns */
TypeCacheEntry *oi_typcache[FLEXIBLE_ARRAY_MEMBER];
} BrinOpcInfo;
Поле BrinOpcInfo.oi_opaque
может использоваться подпрограммами класса оператора для передачи информации между вспомогательными функциями во время сканирования индекса.
bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey *keys, int nkeys)
Возвращает, соответствуют ли все записи ScanKey заданным индексированным значениям для диапазона. Номер атрибута, который будет использоваться, передается как часть ключа сканирования. Можно передавать сразу несколько ключей сканирования для о дного и того же атрибута; количество записей определяется параметром nkeys.
bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey key)
Возвращает, соответствует ли ScanKey заданным индексированным значениям для диапазона. Номер атрибута, который нужно использовать, передается как часть ключа сканирования. Это устаревший обратно совместимый вариант функции consistent
.
bool addValue(BrinDesc *bdesc, BrinValues *column, Datum newval, bool isnull)
Учитывая кортеж индексов и индексируемое значение, изменяет указанный атрибут кортежа таким образом, чтобы он дополнительно представлял новое значение. Если кортеж был модифицирован, возвращается true
.
bool unionTuples(BrinDesc *bdesc, BrinValues *a, BrinValues *b)
Объединяет два индексных кортежа. Учитывая два индексных кортежа, изменяет указанный атрибут первого из них так, чтобы он представлял оба кортежа. Второй кортеж не модифицируется.
Класс оператора для BRIN может опционально предоставить следующий метод:
void options(local_relopts *relopts)
Определяет набор видимых пользователю параметров, которые управляют поведением класса оператора.
Функции options
передается указатель на структуру local_relopts
, которая должна быть заполнена набором опций, специфичных для класса оператора. Доступ к опциям можно получить из других функций поддержки с помощью макросов PG_HAS_OPCLASS_OPTIONS()
и PG_GET_OPCLASS_OPTIONS()
.
Поскольку и извлечение ключа из индексированных значений, и представление ключа в BRIN являются гибкими, они могут зависеть от заданных пользователем параметров.
В основной дистрибутив включена поддержка четырех типов классов операторов: minmax
, minmax-multi
, inclusion
и bloom
. Определения классов операторов, использующих их, поставляются для типов данных ядра по мере необходимости. Дополнительные классы операторов могут быть определены пользователем для других типов данных с использованием эквивалентных определений, без необходимости написания исходного кода; достаточно объявить соответствующие записи в каталоге. Обратите внимание, что предположения о семантике стратегий операторов заложены в исходный код вспомогательных функций.
Классы операторов, реализующие совершенно другую семантику, также возможны при условии, что будут написаны реализаци и четырех основных функций поддержки, описанных выше. Обратите внимание, что обратная совместимость между основными выпусками не гарантируется: например, в более поздних выпусках могут потребоваться дополнительные вспомогательные функции.
Чтобы написать класс оператора для типа данных, реализующего полностью упорядоченное множество, можно использовать вспомогательные функции minmax
наряду с соответствующими операторами, как показано в таблице «Номера стратегий и опорных функций для классов операторов minmax». Все члены операторного класса (функции и операторы) являются обязательными.
Номера стратегий и опорных функций для классов операторов minmax:
Член класса оператора | Объект |
---|---|
Опорная функция 1 | Внутренняя функция brin_minmax_opcinfo() |
Опорная функция 2 | Внутренняя функция brin_minmax_add_value() |
Опорная функция 3 | Внутренняя функция brin_minmax_consistent() |
Опорная функция 4 | Внутренняя функция brin_minmax_union() |
Стратегия оператора 1 | Оператор меньше |
Стратегия оператора 2 | Оператор меньше или равно |
Стратегия оператора 3 | Оператор равно |
Стратегия оператора 4 | Оператор больше или равно |
Стратегия оператора 5 | Оператор больше |
Чтобы написать класс оператора для сложного типа данных, значения которого включены в другой тип, можно использовать функции поддержки включения наряду с соответствующими операторами, как показано в таблице «Номера стратегий и опорных функций для классов операторов inclusion». Для этого требуется только одна дополнительная функция, которую можно написать на любом языке. Для дополнительной функциональности можно определить больше функций. Все операторы являются необязательными. Некоторые операторы требуют других операторов, как показано в таблице в виде зависимостей.
Номера стратегий и опорных функций для классов операторов inclusion:
Член класса оператора | Объект | Зависимость |
---|---|---|
Опорная функция 1 | Внутренняя функция brin_inclusion_opcinfo() | |
Опорная функция 2 | Внутренняя функция brin_inclusion_add_value() | |
Опорная функция 3 | Внутренняя функция brin_inclusion_consistent() | |
Опорная функция 4 | Внутренняя функция brin_inclusion_union() | |
Опорная функция 11 | Функция для объединения двух элементов | |
Опорная функция 12 | Необязательная функция для проверки того, являются ли два элемента объединяемыми | |
Опорная функция 13 | Необязательная функция для проверки того, находится ли элемент внутри другого элемента | |
Опорная функция 14 | Необязательная функция для проверки того, является ли элемент пустым | |
Стратегия оператора 1 | Оператор левее | Стратегия оператора 4 |
Стратегия оператора 2 | Оператор не-простирается-правее | Стратегия оператора 5 |
Стратегия оператора 3 | Оператор перекрывается | |
Стратегия оператора 4 | Оператор не-простирается-левее | Стратегия оператора 1 |
Стратегия оператора 5 | Оператор правее | Стратегия оператора 2 |
Стратегия оператора 6, 18 | Оператор то-же-или-равно | Стратегия оператора 7 |
Стратегия оператора 7, 16, 24, 25 | Оператор содержит-или-равно | |
Стратегия операто ра 8, 26, 27 | Оператор содержится-в-или-равно | Стратегия оператора 3 |
Стратегия оператора 9 | Оператор не-простирается-выше | Стратегия оператора 11 |
Стратегия оператора 10 | Оператор ниже | Стратегия оператора 12 |
Стратегия оператора 11 | Оператор выше | Стратегия оператора 9 |
Стратегия оператора 12 | Оператор не-простирается-ниже | Стратегия оператора 10 |
Стратегия оператора 20 | Оператор меньше | Стратегия оператора 5 |
Стратегия оператора 21 | Оператор меньше-или-равно | Стратегия оператора 5 |
Стратегия оператора 22 | Оператор больше | Стратегия оператора 1 |
Стратегия оператора 23 | Оператор больше-или-равно | Стратегия оператора 1 |
Номера функций поддержки с 1 по 10 зарезервированы для внутренних функций BRIN, поэтому функции уровня SQL начинаются с номера 11. Вспомогательная функция под номером 11 - это основная функция, необходимая для построения индекса. Она должна принимать два аргумента с тем же типом данных, что и класс оператора, и возвращать их объединение. Класс оператора включения может хранить значения объединения с разными типами данных, если он определен с помощью параметра STORAGE
. Возвращаемое значение функции объединения должно соответствовать типу данных STORAGE
.
Функции поддержки под номерами 12 и 14 предназначены для поддержки неоднородности встроенных типов данных. Функция под номером 12 используется для поддержки сетевых адресов из разных семейств, которые не могут быть объединены. Функция номер 14 используется для поддержки пустых диапазонов. Функция № 13 - необязательная, но рекомендуемая, она позволяет проверить новое значение перед передачей его в функцию объединения. Поскольку фреймворк BRIN может сокращать некоторые операции, когда объединение не изменяется, использование этой функции может улучшить производительность индекса.
Чтобы написать класс оператора для типа данных, реализующего только оператор равенства и поддерживающего хеширование, можно использовать процедуры поддержки bloom наряду с соответствующими операторами, как показано в таблице «Номера стратегий и опорных процедур для классов операторов bloom». Все члены класса оператора (процедуры и операторы) являются обязательными.
Номера стратегий и опорных процедур для классов операторов bloom:
Член класса оператора | Объект |
---|---|
Опорная процедура 1 | Внутренняя функция brin_bloom_opcinfo() |
Опорная процедура 2 | Внутренняя функция brin_bloom_add_value() |
Опорная процедура 3 | Внутренняя функция brin_bloom_consistent() |
Опорная процедура 4 | Внутренняя функция brin_bloom_union() |
Опорная процедура 5 | Внутренняя функция brin_bloom_options() |
Опорная процедура 11 | Функция вычисления хеша элемента |
Стратегия оператора 1 | Оператор равно |
Номера вспомогательных процедур 1-10 зарезервированы для внутренних функций BRIN, поэтому функции уровня SQL начинаются с номера 11. Вспомогательная функция под номером 11 - это основная функция, необходимая для построения индекса. Она должна принимать один аргумент с тем же типом данных, что и класс оператора, и возвращать хэш-значение.
Класс операторов minmax-multi также предназначен для типов данных, реализующих полностью упорядоченное множество, и может рассматриваться как простое расширение класса операторов minmax. Если оператор minmax суммирует значения из каждого блока диапазона в один непрерывный интервал, то minmax-multi позволяет суммировать значения в несколько меньших интервалов, что улучшает работу с отклоняющимися значениями. Процедуры поддержки minmax-multi можно использовать наряду с соответствующими операторами, как показано в таблице «Номера стратегий и опорных процедур для классов операторов minmax-multi». Все члены класса операторов (процедуры и операторы) являются обязательными.
Номера стратегий и опорных процедур для классов операторов minmax-multi:
Член класса оператора | Объект |
---|---|
Опорная процедура 1 | Внутренняя функция brin_minmax_multi_opcinfo() |
Опорная процедура 2 | Внутренняя функция brin_minmax_multi_add_value() |
Опорная процедура 3 | Внутренняя функция brin_minmax_multi_consistent() |
Опорная процедура 4 | Внутренняя функция brin_minmax_multi_union() |
Опорная процедура 5 | Внутренняя функция brin_minmax_multi_options() |
Опорная процедура 11 | Функция вычисления расстояния между двумя значениями (длина диапазона) |
Стратегия оператора 1 | Оператор меньше |
Стратегия оператора 2 | Оператор меньше-или-равно |
Стратегия оператора 3 | Оператор равно |
Стратегия оператора 4 | Оператора больше-или-равно |
Стратегия оператора 5 | Оператора больше |
Оба класса операторов minmax и inclusion поддерживают операторы с перекрестными типами данных, хотя в этом случае зависимости становятся более сложными. Класс операторов minmax требует определения полного набора операторов, оба аргумента которых имеют одинаковый тип данных. Он позволяет поддерживать дополнительные типы данных, определяя дополнительные наборы операторов. Операторные стратегии класса операторов включения зависят от другой операторной стратегии, как показано в таблице «Номера стратегий и опорных функций для классов операторов inclusion», или от той же самой операторной стратегии как таковой. Они требуют, чтобы оператор зависимости был определен с типом данных STORAGE
в качестве аргумента левой стороны, а другой поддерживаемый тип данных - в качестве аргумента правой сто роны поддерживаемого оператора. См. float4_minmax_ops
в качестве примера minmax и box_inclusion_ops
в качестве примера inclusion.