64.5. Индексы BRIN#
64.5. Индексы BRIN #
64.5.1. Введение #
BRIN расшифровывается как Block Range Index. BRIN предназначен для работы с очень большими таблицами, в которых определенные столбцы имеют естественную корреляцию с их физическим расположением внутри таблицы.
BRIN работает в терминах диапазонов блоков (или “диапазонов страниц”). Диапазон блоков - это группа страниц, которые физически смежны в таблице; для каждого диапазона блоков хранится некоторая сводная информация в индексе. Например, таблица, хранящая заказы на продажу магазина, может иметь столбец с датой, на которой был размещен каждый заказ, и большую часть времени записи для более ранних заказов будут появляться раньше в таблице; таблица, хранящая столбец с почтовым индексом, может иметь все коды для города естественно сгруппированы вместе.
BRIN индексы могут удовлетворять запросы с помощью обычных сканирований индекса битовой карты и будут возвращать все кортежи на всех страницах в каждом диапазоне, если информация, хранящаяся в индексе, согласована с условиями запроса. Исполнитель запроса отвечает за повторную проверку этих кортежей и отбрасывание тех, которые не соответствуют условиям запроса — другими словами, эти индексы являются потерянными. Поскольку BRIN индекс очень маленький, сканирование индекса добавляет мало дополнительные издержки по сравнению с последовательным сканированием, но может избежать сканирования больших частей таблицы, в которых известно, что нет соответствующих кортежей.
Специфические данные, которые будет хранить индекс BRIN, а также конкретные запросы, которые индекс сможет удовлетворить, зависят от выбранного класса операторов для каждого столбца индекса. Типы данных, имеющие линейный порядок сортировки, могут иметь классы операторов, которые хранят минимальное и максимальное значение в каждом блочном диапазоне, например; геометрические типы могут хранить ограничивающий прямоугольник для всех объектов в блочном диапазоне.
Размер диапазона блоков определяется во время создания индекса с помощью параметра хранения pages_per_range
. Количество записей индекса будет равно размеру отношения в страницах, разделенному на выбранное значение pages_per_range
. Следовательно, чем меньше число, тем больше становится индекс (из-за необходимости хранить больше записей индекса), но в то же время хранящиеся сводные данные могут быть более точными, и во время сканирования индекса можно пропустить больше блоков данных.
64.5.1.1. Обслуживание индексов #
В момент создания сканируются все существующие страницы кучи и для каждого диапазона создается сводный индексный кортеж, включая возможно неполный диапазон в конце. По мере заполнения новыми данными страницы, диапазоны страниц, которые уже были сводно описаны, приводят к обновлению сводной информации с данными из новых кортежей. Когда создается новая страница, которая не попадает в последний сводно описанный диапазон, диапазон, к которому принадлежит новая страница, не получает автоматически сводного кортежа; эти кортежи остаются несводно описанными до тех пор, пока не будет вызвана операция сводного описания позже, создающая начальное сводное описание для этого диапазона.
Существует несколько способов запустить начальное суммирование диапазона страниц. Если таблица очищается вручную или с помощью автоочистки, все существующие несуммированные диапазоны страниц суммируются. Кроме того, если параметр autosummarize индекса включен, что по умолчанию не так, всякий раз, когда автоочистка запускается в этой базе данных, будет выполняться суммирование всех несуммированных заполненных диапазонов страниц, независимо от того, обрабатывается ли сама таблица автоочисткой; см. ниже.
Наконец, можно использовать следующие функции (пока эти функции выполняются,
search_path временно изменяется на
pg_catalog, pg_temp
):
brin_summarize_new_values(regclass)
которая суммирует все несуммированные диапазоны; |
brin_summarize_range(regclass, bigint)
которая суммирует только диапазон, содержащий данную страницу,
если он не был ранее суммирован. |
Когда включена автоматическая суммаризация, отправляется запрос к autovacuum
для выполнения целевой суммаризации для диапазона блоков, когда обнаруживается вставка для первого элемента первой страницы следующего диапазона блоков, чтобы быть выполненным в следующий раз, когда рабочий процесс автоматической очистки завершит работу в той же базе данных. Если очередь запросов заполнена, запрос не записывается, и в журнал сервера отправляется сообщение:
LOG: request for BRIN range summarization for index "brin_wi_idx" page 128 was not recorded
Когда это происходит, диапазон останется несуммированным до следующего регулярного запуска очистки на таблице или вызова одной из вышеупомянутых функций.
Обратно, диапазон может быть развернут с использованием функции brin_desummarize_range(regclass, bigint)
, которая полезна, когда кортеж индекса больше не является очень хорошим представлением, потому что существующие значения изменились. См. Раздел 9.28.8 для получения подробной информации.
64.5.2. Встроенные классы операторов #
Основной дистрибутив Tantor SE включает классы операторов BRIN, показанные в Таблица 64.4.
Операторные классы minmax хранят минимальное и максимальное значения, появляющиеся в индексируемом столбце в пределах диапазона. Операторные классы inclusion хранят значение, которое включает значения в индексируемом столбце в пределах диапазона. Операторные классы bloom создают фильтр Блума для всех значений в диапазоне. Операторные классы minmax-multi хранят несколько минимальных и максимальных значений, представляющих значения, появляющиеся в индексируемом столбце в пределах диапазона.
Таблица 64.4. Встроенные классы операторов BRIN
Имя | Индексируемые операторы |
---|---|
bit_minmax_ops | = (bit,bit) |
< (bit,bit) | |
> (bit,bit) | |
<= (bit,bit) | |
>= (bit,bit) | |
box_inclusion_ops | @> (box,point) |
<< (box,box) | |
&< (box,box) | |
&> (box,box) | |
>> (box,box) | |
<@ (box,box) | |
@> (box,box) | |
~= (box,box) | |
&& (box,box) | |
<<| (box,box) | |
&<| (box,box) | |
|&> (box,box) | |
|>> (box,box) | |
bpchar_bloom_ops | = (character,character) |
bpchar_minmax_ops | = (character,character) |
< (character,character) | |
<= (character,character) | |
> (character,character) | |
>= (character,character) | |
bytea_bloom_ops | = (bytea,bytea) |
bytea_minmax_ops | = (bytea,bytea) |
< (bytea,bytea) | |
<= (bytea,bytea) | |
> (bytea,bytea) | |
>= (bytea,bytea) | |
char_bloom_ops | = ("char","char") |
char_minmax_ops | = ("char","char") |
< ("char","char") | |
<= ("char","char") | |
> ("char","char") | |
>= ("char","char") | |
date_bloom_ops | = (date,date) |
date_minmax_ops | = (date,date) |
< (date,date) | |
<= (date,date) | |
> (date,date) | |
>= (date,date) | |
date_minmax_multi_ops | = (date,date) |
< (date,date) | |
<= (date,date) | |
> (date,date) | |
>= (date,date) | |
float4_bloom_ops | = (float4,float4) |
float4_minmax_ops | = (float4,float4) |
< (float4,float4) | |
> (float4,float4) | |
<= (float4,float4) | |
>= (float4,float4) | |
float4_minmax_multi_ops | = (float4,float4) |
< (float4,float4) | |
> (float4,float4) | |
<= (float4,float4) | |
>= (float4,float4) | |
float8_bloom_ops | = (float8,float8) |
float8_minmax_ops | = (float8,float8) |
< (float8,float8) | |
<= (float8,float8) | |
> (float8,float8) | |
>= (float8,float8) | |
float8_minmax_multi_ops | = (float8,float8) |
< (float8,float8) | |
<= (float8,float8) | |
> (float8,float8) | |
>= (float8,float8) | |
inet_inclusion_ops | << (inet,inet) |
<<= (inet,inet) | |
>> (inet,inet) | |
>>= (inet,inet) | |
= (inet,inet) | |
&& (inet,inet) | |
inet_bloom_ops | = (inet,inet) |
inet_minmax_ops | = (inet,inet) |
< (inet,inet) | |
<= (inet,inet) | |
> (inet,inet) | |
>= (inet,inet) | |
inet_minmax_multi_ops | = (inet,inet) |
< (inet,inet) | |
<= (inet,inet) | |
> (inet,inet) | |
>= (inet,inet) | |
int2_bloom_ops | = (int2,int2) |
int2_minmax_ops | = (int2,int2) |
< (int2,int2) | |
> (int2,int2) | |
<= (int2,int2) | |
>= (int2,int2) | |
int2_minmax_multi_ops | = (int2,int2) |
< (int2,int2) | |
> (int2,int2) | |
<= (int2,int2) | |
>= (int2,int2) | |
int4_bloom_ops | = (int4,int4) |
int4_minmax_ops | = (int4,int4) |
< (int4,int4) | |
> (int4,int4) | |
<= (int4,int4) | |
>= (int4,int4) | |
int4_minmax_multi_ops | = (int4,int4) |
< (int4,int4) | |
> (int4,int4) | |
<= (int4,int4) | |
>= (int4,int4) | |
int8_bloom_ops | = (bigint,bigint) |
int8_minmax_ops | = (bigint,bigint) |
< (bigint,bigint) | |
> (bigint,bigint) | |
<= (bigint,bigint) | |
>= (bigint,bigint) | |
int8_minmax_multi_ops | = (bigint,bigint) |
< (bigint,bigint) | |
> (bigint,bigint) | |
<= (bigint,bigint) | |
>= (bigint,bigint) | |
interval_bloom_ops | = (interval,interval) |
interval_minmax_ops | = (interval,interval) |
< (interval,interval) | |
<= (interval,interval) | |
> (interval,interval) | |
>= (interval,interval) | |
interval_minmax_multi_ops | = (interval,interval) |
< (interval,interval) | |
<= (interval,interval) | |
> (interval,interval) | |
>= (interval,interval) | |
macaddr_bloom_ops | = (macaddr,macaddr) |
macaddr_minmax_ops | = (macaddr,macaddr) |
< (macaddr,macaddr) | |
<= (macaddr,macaddr) | |
> (macaddr,macaddr) | |
>= (macaddr,macaddr) | |
macaddr_minmax_multi_ops | = (macaddr,macaddr) |
< (macaddr,macaddr) | |
<= (macaddr,macaddr) | |
> (macaddr,macaddr) | |
>= (macaddr,macaddr) | |
macaddr8_bloom_ops | = (macaddr8,macaddr8) |
macaddr8_minmax_ops | = (macaddr8,macaddr8) |
< (macaddr8,macaddr8) | |
<= (macaddr8,macaddr8) | |
> (macaddr8,macaddr8) | |
>= (macaddr8,macaddr8) | |
macaddr8_minmax_multi_ops | = (macaddr8,macaddr8) |
< (macaddr8,macaddr8) | |
<= (macaddr8,macaddr8) | |
> (macaddr8,macaddr8) | |
>= (macaddr8,macaddr8) | |
name_bloom_ops | = (name,name) |
name_minmax_ops | = (name,name) |
< (name,name) | |
<= (name,name) | |
> (name,name) | |
>= (name,name) | |
numeric_bloom_ops | = (numeric,numeric) |
numeric_minmax_ops | = (numeric,numeric) |
< (numeric,numeric) | |
<= (numeric,numeric) | |
> (numeric,numeric) | |
>= (numeric,numeric) | |
numeric_minmax_multi_ops | = (numeric,numeric) |
< (numeric,numeric) | |
<= (numeric,numeric) | |
> (numeric,numeric) | |
>= (numeric,numeric) | |
oid_bloom_ops | = (oid,oid) |
oid_minmax_ops | = (oid,oid) |
< (oid,oid) | |
> (oid,oid) | |
<= (oid,oid) | |
>= (oid,oid) | |
oid_minmax_multi_ops | = (oid,oid) |
< (oid,oid) | |
> (oid,oid) | |
<= (oid,oid) | |
>= (oid,oid) | |
pg_lsn_bloom_ops | = (pg_lsn,pg_lsn) |
pg_lsn_minmax_ops | = (pg_lsn,pg_lsn) |
< (pg_lsn,pg_lsn) | |
> (pg_lsn,pg_lsn) | |
<= (pg_lsn,pg_lsn) | |
>= (pg_lsn,pg_lsn) | |
pg_lsn_minmax_multi_ops | = (pg_lsn,pg_lsn) |
< (pg_lsn,pg_lsn) | |
> (pg_lsn,pg_lsn) | |
<= (pg_lsn,pg_lsn) | |
>= (pg_lsn,pg_lsn) | |
range_inclusion_ops | = (anyrange,anyrange) |
< (anyrange,anyrange) | |
<= (anyrange,anyrange) | |
>= (anyrange,anyrange) | |
> (anyrange,anyrange) | |
&& (anyrange,anyrange) | |
@> (anyrange,anyelement) | |
@> (anyrange,anyrange) | |
<@ (anyrange,anyrange) | |
<< (anyrange,anyrange) | |
>> (anyrange,anyrange) | |
&< (anyrange,anyrange) | |
&> (anyrange,anyrange) | |
-|- (anyrange,anyrange) | |
text_bloom_ops | = (text,text) |
text_minmax_ops | = (text,text) |
< (text,text) | |
<= (text,text) | |
> (text,text) | |
>= (text,text) | |
tid_bloom_ops | = (tid,tid) |
tid_minmax_ops | = (tid,tid) |
< (tid,tid) | |
> (tid,tid) | |
<= (tid,tid) | |
>= (tid,tid) | |
tid_minmax_multi_ops | = (tid,tid) |
< (tid,tid) | |
> (tid,tid) | |
<= (tid,tid) | |
>= (tid,tid) | |
timestamp_bloom_ops | = (timestamp,timestamp) |
timestamp_minmax_ops | = (timestamp,timestamp) |
< (timestamp,timestamp) | |
<= (timestamp,timestamp) | |
> (timestamp,timestamp) | |
>= (timestamp,timestamp) | |
timestamp_minmax_multi_ops | = (timestamp,timestamp) |
< (timestamp,timestamp) | |
<= (timestamp,timestamp) | |
> (timestamp,timestamp) | |
>= (timestamp,timestamp) | |
timestamptz_bloom_ops | = (timestamptz,timestamptz) |
timestamptz_minmax_ops | = (timestamptz,timestamptz) |
< (timestamptz,timestamptz) | |
<= (timestamptz,timestamptz) | |
> (timestamptz,timestamptz) | |
>= (timestamptz,timestamptz) | |
timestamptz_minmax_multi_ops | = (timestamptz,timestamptz) |
< (timestamptz,timestamptz) | |
<= (timestamptz,timestamptz) | |
> (timestamptz,timestamptz) | |
>= (timestamptz,timestamptz) | |
time_bloom_ops | = (time,time) |
time_minmax_ops | = (time,time) |
< (time,time) | |
<= (time,time) | |
> (time,time) | |
>= (time,time) | |
time_minmax_multi_ops | = (time,time) |
< (time,time) | |
<= (time,time) | |
> (time,time) | |
>= (time,time) | |
timetz_bloom_ops | = (timetz,timetz) |
timetz_minmax_ops | = (timetz,timetz) |
< (timetz,timetz) | |
<= (timetz,timetz) | |
> (timetz,timetz) | |
>= (timetz,timetz) | |
timetz_minmax_multi_ops | = (timetz,timetz) |
< (timetz,timetz) | |
<= (timetz,timetz) | |
> (timetz,timetz) | |
>= (timetz,timetz) | |
uuid_bloom_ops | = (uuid,uuid) |
uuid_minmax_ops | = (uuid,uuid) |
< (uuid,uuid) | |
> (uuid,uuid) | |
<= (uuid,uuid) | |
>= (uuid,uuid) | |
uuid_minmax_multi_ops | = (uuid,uuid) |
< (uuid,uuid) | |
> (uuid,uuid) | |
<= (uuid,uuid) | |
>= (uuid,uuid) | |
varbit_minmax_ops | = (varbit,varbit) |
< (varbit,varbit) | |
> (varbit,varbit) | |
<= (varbit,varbit) | |
>= (varbit,varbit) |
64.5.2.1. Параметры класса операторов #
Некоторые из встроенных классов операторов позволяют указывать параметры, влияющие на поведение класса операторов. У каждого класса операторов есть свой набор разрешенных параметров. Только классы операторов bloom
и minmax-multi
позволяют указывать параметры:
bloom классы операторов принимают следующие параметры:
n_distinct_per_range
Определяет ожидаемое количество уникальных ненулевых значений в диапазоне блоков, используемых индексами Блума BRIN для определения размера фильтра Блума. Он ведет себя аналогично опции
n_distinct
для ALTER TABLE. Когда установлено положительное значение, предполагается, что каждый диапазон блоков содержит это количество уникальных ненулевых значений. Когда установлено отрицательное значение, которое должно быть больше или равно -1, предполагается, что количество уникальных ненулевых значений растет линейно с максимально возможным количеством кортежей в диапазоне блоков (приблизительно 290 строк на блок). Значение по умолчанию --0.1
, а минимальное количество уникальных ненулевых значений -16
.false_positive_rate
Определяет желаемую частоту ложных срабатываний, используемую индексами Блума BRIN для определения размера фильтра Блума. Значения должны быть в диапазоне от 0.0001 до 0.25. Значение по умолчанию - 0.01, что соответствует 1% частоте ложных срабатываний.
классы операторов minmax-multi принимают следующие параметры:
values_per_range
Определяет максимальное количество значений, хранящихся индексами BRIN minmax для суммирования диапазона блоков. Каждое значение может представлять либо точку, либо границу интервала. Значения должны быть в диапазоне от 8 до 256, а значение по умолчанию - 32.
64.5.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 вместе с соответствующими операторами, как показано в Таблица 64.5. Все члены класса операторов (функции и операторы) являются обязательными.
Таблица 64.5. Функции и номера опорных функций для классов операторов Minmax
Оператор класса член | Объект |
---|---|
Опорная функция 1 | внутренняя функция brin_minmax_opcinfo() |
Опорная функция 2 | внутренняя функция brin_minmax_add_value() |
Опорная функция 3 | внутренняя функция brin_minmax_consistent() |
Опорная функция 4 | внутренняя функция brin_minmax_union() |
Стратегия оператора 1 | оператор меньше-чем |
Стратегия оператора 2 | оператор меньше или равно |
Стратегия оператора 3 | оператор равенства |
Стратегия оператора 4 | оператор больше или равно |
Стратегия оператора 5 | оператор больше-чем |
Для написания класса операторов для сложного типа данных, значения которого включены в другой тип, можно использовать функции поддержки включения вместе с соответствующими операторами, как показано в разделе Таблица 64.6. Для этого требуется всего одна дополнительная функция, которая может быть написана на любом языке. Дополнительные функции могут быть определены для расширения функциональности. Все операторы являются необязательными. Некоторые операторы требуют наличия других операторов, как показано в зависимостях в таблице.
Таблица 64.6. Функции и номера опорных функций для классов операторов включения
Оператор класса член | Объект | Зависимость |
---|---|---|
Опорная функция 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 вместе с соответствующими операторами, как показано в разделе Таблица 64.7. Все элементы класса операторов (процедуры и операторы) являются обязательными.
Таблица 64.7. Номера процедур и опорных функций для классов операторов 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 вместе с соответствующими операторами, как показано в Таблица 64.8. Все элементы класса операторов (процедуры и операторы) являются обязательными.
Таблица 64.8. Номера процедур и опорных функций для классов операторов 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 зависят от другой стратегии операторов, как показано в Таблица 64.6, или от той же стратегии операторов, что и сами они. Они требуют, чтобы оператор зависимости был определен с типом данных STORAGE
в качестве аргумента слева и другим поддерживаемым типом данных в качестве аргумента справа для поддерживаемого оператора. См. float4_minmax_ops
в качестве примера minmax и box_inclusion_ops
в качестве примера inclusion.