69.3. Расширяемость#
69.3. Расширяемость
Интерфейс BRIN имеет высокий уровень абстракции, требуя от реализатора метода доступа только реализовать семантику обрабатываемого типа данных. Сам слой BRIN заботится о параллельности, журналировании и поиске в структуре индекса.
Все, что нужно сделать, чтобы заработал метод доступа BRIN, это реализовать несколько пользовательских методов, которые определяют поведение сводных значений, хранящихся в индексе, и их взаимодействие с ключами сканирования. Короче говоря, BRIN сочетает в себе расширяемость с общностью, повторное использование кода и чистый интерфейс.
Существует четыре метода, которые операторный класс для BRIN должен предоставить:
BrinOpcInfo *opcInfo(Oid type_oid)
Возвращает внутреннюю информацию о сводных данных индексированных столбцов. Возвращаемое значение должно указывать на выделенную с помощью palloc структуру
BrinOpcInfo
, которая имеет следующее определение: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 вместе с соответствующими операторами, как показано в Таблица 69.2. Все члены класса операторов (функции и операторы) являются обязательными.
Таблица 69.2. Функции и номера опорных функций для классов операторов Minmax
Оператор класса член | Объект |
---|---|
Опорная функция 1 | внутренняя функция brin_minmax_opcinfo() |
Опорная функция 2 | внутренняя функция brin_minmax_add_value() |
Опорная функция 3 | внутренняя функция brin_minmax_consistent() |
Опорная функция 4 | внутренняя функция brin_minmax_union() |
Стратегия оператора 1 | оператор меньше-чем |
Стратегия оператора 2 | оператор меньше или равно |
Стратегия оператора 3 | оператор равенства |
Стратегия оператора 4 | оператор больше или равно |
Стратегия оператора 5 | оператор больше-чем |
Для написания класса операторов для сложного типа данных, значения которого включены в другой тип, можно использовать функции поддержки включения вместе с соответствующими операторами, как показано в разделе Таблица 69.3. Для этого требуется всего одна дополнительная функция, которая может быть написана на любом языке. Дополнительные функции могут быть определены для расширения функциональности. Все операторы являются необязательными. Некоторые операторы требуют наличия других операторов, как показано в зависимостях в таблице.
Таблица 69.3. Функции и номера опорных функций для классов операторов включения
Оператор класса член | Объект | Зависимость |
---|---|---|
Опорная функция 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 | оператор same-as-or-equal-to | Стратегия оператора 7 |
Стратегия оператора 7, 16, 24, 25 | оператор содержит-или-равно | |
Стратегия оператора 8, 26, 27 | оператор is-contained-by-or-equal-to | Стратегия оператора 3 |
Стратегия оператора 9 | оператор не расширяется выше | Стратегия оператора 11 |
Стратегия оператора 10 | оператор is-below | Стратегия оператора 12 |
Стратегия оператора 11 | оператор is-above | Стратегия оператора 9 |
Стратегия оператора 12 | оператор does-not-extend-below | Стратегия оператора 10 |
Стратегия оператора 20 | оператор меньше-чем | Стратегия оператора 5 |
Стратегия оператора 21 | оператор меньше или равно | Стратегия оператора 5 |
Стратегия оператора 22 | оператор больше-чем | Стратегия оператора 1 |
Стратегия оператора 23 | оператор больше или равно | Стратегия оператора 1 |
Опорные функции с номерами от 1 до 10 зарезервированы для внутренних функций BRIN, поэтому функции на уровне SQL начинаются с номера 11. Опорная функция с номером 11 - это основная функция, необходимая для построения индекса. Она должна принимать два аргумента с тем же типом данных, что и класс оператора, и возвращать их объединение. Класс оператора включения может хранить объединенные значения с разными типами данных, если он определен с параметром STORAGE
. Возвращаемое значение функции объединения должно соответствовать типу данных STORAGE
.
Поддерживаются функции номер 12 и 14 для поддержки нерегулярностей встроенных типов данных. Функция номер 12 используется для поддержки сетевых адресов разных семейств, которые не могут быть объединены. Функция номер 14 используется для поддержки пустых диапазонов. Функция номер 13 является необязательной, но рекомендуется, так как она позволяет проверить новое значение перед его передачей в функцию объединения. Поскольку фреймворк BRIN может оптимизировать некоторые операции, когда объединение не изменяется, использование этой функции может улучшить производительность индекса.
Для написания класса операторов для типа данных, который реализует только оператор равенства и поддерживает хеширование, можно использовать процедуры поддержки bloom вместе с соответствующими операторами, как показано в разделе Таблица 69.4. Все элементы класса операторов (процедуры и операторы) являются обязательными.
Таблица 69.4. Номера процедур и опорных функций для классов операторов 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 вместе с соответствующими операторами, как показано в Таблица 69.5. Все элементы класса операторов (процедуры и операторы) являются обязательными.
Таблица 69.5. Номера процедур и опорных функций для классов операторов 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 зависят от другой стратегии операторов, как показано в Таблица 69.3, или от той же стратегии операторов, что и сами они. Они требуют, чтобы оператор зависимости был определен с типом данных STORAGE
в качестве аргумента слева и другим поддерживаемым типом данных в качестве аргумента справа для поддерживаемого оператора. См. float4_minmax_ops
в качестве примера minmax и box_inclusion_ops
в качестве примера inclusion.