Индексы BRIN
Введение
BRIN расшифровывается как Block Range Index (индекс диапазона блоков). BRIN предназначен для обработки очень больших таблиц, в которых определенные столбцы имеют некую естественную корреляцию с их физическим расположением в таблице.
BRIN работает в категориях диапазонов блоков (или «диапазонов страниц»). Диапазон блоков — это группа страниц, которые физически соседствуют в таблице; для каждого диапазона блоков в индексе сохраняется некоторая сводная информация. Например, таблица, хранящая заказы на поставку, может иметь столбец даты добавления каждого заказа, и в большинстве случаев записи для более ранних заказов в таблице будут размещены выше; в таблице со столбцом почтового индекса могут храниться все коды городов, сгруппированные естественным образом.
Индексы BRIN удовлетворяют запросы посредством обычного сканирования по битовой карте, возвращая все кортежи всех страниц в каждом диапазоне, если сводная информация, сохраненная в индексе, согласуется с условиями запроса. Исполнитель запроса отвечает за перепроверку этих кортежей и сброс тех, что не соответствуют условиям запроса — другими словами, эти индексы крайне неточные. Но поскольку индекс BRIN очень мал, его сканирование добавляет мало издержек по сравнению с последовательным сканированием, при этом помогая избежать сканирования больших областей таблицы, которые точно не содержат подходящих кортежей.
Конкретные данные, которые будет хранить индекс BRIN, а также конкретные запросы, которые этот индекс сможет удовлетворить, зависят от класса операторов, выбранного для каждого столбца индекса. Например, типы данных с линейным порядком сортировки могут иметь классы операторов, которые хранят минимальное и максимальное значение в каждом диапазоне блоков; геометрические типы могут хранить ограничивающую рамку для всех объектов в диапазоне блоков.
Размер диапазона блоков определяется во время создания индекса параметром хранения pages_per_range. Количество записей индекса будет равно размеру отношения в страницах, деленному на выбранное значение pages_per_range. Таким образом, чем меньше это число, тем больше размер индекса (из-за необходимости хранить больше записей), но в то же время может повыситься точность сохраняемой сводной информации, а во время сканирования можно будет пропустить больше блоков данных.
Обслуживание индекса
Во время создания индекса сканируются все существующие страницы кучи, и для каждого диапазона, включая возможно неполный диапазон в конце, создается сводный кортеж индекса. По мере того, как данными наполняются новые страницы, в диапазонах страниц, для которых уже есть сводная информация, эта информация обновляется данными из новых кортежей. Когда создается новая страница, не попадающая в последний диапазон, для которого есть сводка, диапазон, которому принадлежит эта новая страница, не получает автоматически кортеж со сводкой; эти кортежи остаются неучтенными, пока позже не запустится расчет сводных данных, создавая начальные сводки для этого диапазона.
Существует несколько способов запустить начальный расчет сводки для диапазона страниц. Если таблица очищается, вручную либо автоочисткой, сводка рассчитывается для всех существующих неучтенных диапазонов страниц. Кроме того, если включен параметр индекса autosummarize (это не значение по умолчанию), при каждой автоочистке этой базы данных сводка рассчитывается для всех неучтенных диапазонов страниц, которые были заполнены, независимо от того, выполняется ли автоочистка самой этой таблицы; см. ниже.
Наконец, можно использовать следующие функции:
- 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 для страницы 128 индекса "brin_wi_idx" не был записан
Когда это происходит, сводка для такого диапазона рассчитывается уже только при выполнении следующей регулярной очистки таблицы или при вызове одной из вышеупомянутых функций.
И наоборот, сводку для диапазона можно удалить с помощью функции brin_desummarize_range(regclass, bigint), что полезно, когда кортеж индекса перестает быть очень хорошим представлением, поскольку существующие значения изменились. Подробную информацию см. в подразделе Функции для обслуживания индексов.
Встроенные классы операторов
Основной дистрибутив QHB включает классы операторов BRIN, показанные в Таблице 1.
Классы операторов minmax хранят минимальное и максимальное значения, встречающиеся в индексированном столбце в пределах определенного диапазона. Классы операторов inclusion хранят значение, в котором содержатся значения индексированного столбца в пределах определенного диапазона. Классы операторов bloom строят фильтр Блума для всех значений в определенном диапазоне. Классы операторов minmax-multi хранят несколько минимальных и максимальных значений, представляющих значения, встречающиеся в индексированном столбце в пределах определенного диапазона.
Таблица 1. Встроенные классы операторов 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) |
Параметры класса операторов
Для некоторых встроенных классов операторов разрешено задавать параметры, влияющие на их поведение. У каждого класса операторов имеется собственный набор допустимых операторов. Указывать параметры можно только для классов операторов bloom и minmax-multi.
Классы операторов bloom принимают следующие параметры:
n_distinct_per_range
Определяет предположительное количество уникальных значений, отличных от NULL, в
диапазоне блоков, используемых индексами BRIN типа bloom для установки размера
фильтра Блума. Его поведение аналогично таковому у параметра n_distinct
команды ALTER TABLE
. Когда задается положительное значение, считается, что
каждый диапазон блоков содержит именно это количество уникальных значений, отличных
от NULL. Когда задается отрицательное значение, которое должно быть больше либо
равно -1, считается, что количество уникальных значений, отличных от NULL, линейно
возрастает в зависимости от максимально возможного количества кортежей в диапазоне
блоков (примерно 290 строк на блок). По умолчанию установлено значение -0.1, а
минимальное количество уникальных значений, отличных от NULL, которое можно
задать, равно 16.
false_positive_rate
Определяет целевую долю ложноположительных срабатываний, используемых индексами
BRIN типа bloom для установки размера фильтра Блума. Значение должно находиться
в пределах от 0.0001 до 0.25. Значение по умолчанию равно 0.01, т. е. доля
ложноположительных срабатываний составляет 1%.
Классы операторов minmax-multi принимают следующие параметры:
values_per_range
Определяет максимальное количество значений, хранимых индексами BRIN типа minmax
для создания сводки по диапазону блоков. Каждое значение может представлять либо
точку, либо границу интервала. Значения должны находиться в пределах от 8 до 256,
а значение по умолчанию равно 32.
Расширяемость
Интерфейс BRIN имеет высокий уровень абстракции, требующий от разработчика метода доступа описать только семантику обрабатываемого типа данных. Сам уровень BRIN обеспечивает параллельный доступ, протоколирование в журнал и поиск в структуре индекса.
Все, что требуется, чтобы получить работающий метод доступа BRIN, — это реализовать несколько пользовательских методов, которые определят поведение сводных значений, хранящихся в индексе, и их взаимодействие с ключами сканирования. Иными словами, BRIN сочетает расширяемость с универсальностью, повторным использованием кода и простым интерфейсом.
Существует четыре метода, которые должен предоставить класс операторов для BRIN:
opcInfo
BrinOpcInfo *opcInfo(Oid type_oid)
Возвращает внутреннюю информацию о сводных данных индексированных столбцов. Возвращаемое значение должно указывать на BrinOpcInfo, выделенную с помощью palloc, имеющую следующее определение:
typedef struct BrinOpcInfo
{
/* Количество столбцов, хранящихся в столбце индекса этого класса операторов */
uint16 oi_nstored;
/* Непрозрачный указатель для внутреннего использования классом операторов */
void *oi_opaque;
/* Записи кэша типов для сохраненных столбцов */
TypeCacheEntry *oi_typcache[FLEXIBLE_ARRAY_MEMBER];
} BrinOpcInfo;
Brinpcinfo.oi_opaque могут использовать процедуры класса операторов для передачи информации между вспомогательными функциями при сканировании индекса.
consistent
bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey *keys, int nkeys)
Показывает, все ли записи ScanKey согласуются с заданными индексированными значениями некоторого диапазона. Номер целевого атрибута передается как часть ключа сканирования. Для одного атрибута может передаваться несколько ключей сканирования; количество записей определяется параметром nkeys.
bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey key)
Показывает, согласуется ли эта запись ScanKey с заданными индексированными значениями некоторого диапазона. Номер целевого атрибута передается как часть ключа сканирования. Это более старый обратно совместимый вариант функции consistent.
addValue
bool addValue(BrinDesc *bdesc, BrinValues *column, Datum newval, bool isnull)
Для заданного кортежа индекса и индексируемого значения изменяет указанный атрибут кортежа, чтобы тот дополнительно представлял новое значение. Если кортеж каким-либо образом менялся, возвращается true.
unionTuples
bool unionTuples(BrinDesc *bdesc, BrinValues *a, BrinValues *b)
Консолидирует два кортежа индекса. Для двух заданных кортежей индекса изменяет
указанный атрибут первого из них, чтобы тот представлял оба кортежа. Второй
кортеж не изменяется.
.
Дополнительно класс операторов для BRIN может задать следующий метод:
options
void options(local_relopts *relopts)
Определяет набор видимых пользователю параметров, управляющих поведением класса
операторов.
Функции options передается указатель на структуру local_relopts, которую
нужно заполнить набором параметров, специфичных для класса операторов. К этим
параметрам можно обращаться из других вспомогательных функций с помощью
макросов PG_HAS_OPCLASS_OPTIONS() и PG_GET_OPCLASS_OPTIONS().
Поскольку в BRIN извлечение ключа из индексируемых значений и представление
этого ключа допускают гибкость, они могут зависеть от параметров, заданных
пользователем.
.
Основной дистрибутив включает поддержку четырех типов классов операторов: minmax, minmax-multi, inclusion и bloom. Использующие их определения классов операторов поставляются для резидентных типов данных по мере необходимости. Для других типов данных пользователь может определить дополнительные классы операторов с помощью равнозначных определений без необходимости писать какой-либо исходный код; достаточно объявить подходящие записи в каталоге. Обратите внимание, что предположения о семантике стратегий операторов зашиты в исходном коде вспомогательных функций.
Также возможно создать классы операторов, воплощающие совершенно иную семантику, предоставив реализации четырех основных вспомогательных функций, описанных выше. Обратите внимание, что обратная совместимость между разными основными версиями не гарантируется: например, в следующих выпусках могут потребоваться дополнительные вспомогательные функции.
Для написания класса операторов для типа данных, реализующего полностью упорядоченное множество, можно воспользоваться вспомогательными функциями minmax наряду с соответствующими операторами, как показано в Таблице 2. Все члены класса операторов (функции и операторы) являются обязательными.
Таблица 2. Номера стратегий и вспомогательных функций для классов операторов minmax
Член класса операторов | Объект |
---|---|
Вспомогательная функция 1 | внутренняя функция brin_minmax_opcinfo() |
Вспомогательная функция 2 | внутренняя функция brin_minmax_add_value() |
Вспомогательная функция 3 | внутренняя функция brin_minmax_consistent() |
Вспомогательная функция 4 | внутренняя функция brin_minmax_union() |
Стратегия оператора 1 | оператор меньше |
Стратегия оператора 2 | оператор меньше-или-равно |
Стратегия оператора 3 | оператор равно |
Стратегия оператора 4 | оператор больше-или-равно |
Стратегия оператора 5 | оператор больше |
Для написания класса операторов для сложного типа данных, значения которого включены в другой тип, можно воспользоваться вспомогательными функциями inclusion наряду с соответствующими операторами, как показано в Таблице 3. Для этого требуется всего одна дополнительная функция, которую можно написать на любом языке. Для дополнительной функциональности можно определить больше функций. Все операторы являются необязательными. Некоторым из них требуется наличие других операторов, что показано в таблице в виде зависимостей.
Таблица 3. Номера стратегий и вспомогательных функций для классов операторов 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 является основной функцией, требуемой для постройки индекса. Она должна принимать два аргумента с тем же типом данных, что и у класса операторов, и возвращать их объединение. Класс операторов inclusion может сохранять объединенные значения в различных типах данных, если это определено в параметре STORAGE. Значение, возвращаемое функцией объединения, должно соответствовать типу данных STORAGE.
Вспомогательные функции номер 12 и номер 14 предоставляются для поддержки нерегулярностей встроенных типов данных. Функция номер 12 используется для поддержки сетевых адресов из различных семейств, которые нельзя объединять. Функция номер 14 используется для поддержки пустых диапазонов. Функция номер 13 является необязательной, но рекомендуемой; она позволяет проверить новое значение, прежде чем оно будет передано функции объединения. Поскольку инфраструктура BRIN может упростить некоторые операции, когда объединение не меняется, использование этой функции может повысить производительность индекса.
Для написания класса операторов для типа данных, реализующего только оператор равенства и поддерживающего хеширование, можно использовать вспомогательные процедуры bloom наряду с соответствующими операторами, как показано в Таблице 4. Все члены класса операторов (процедуры и операторы) являются обязательными.
Таблица 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 наряду с соответствующими операторами, как показано в Таблице 5. Все члены класса операторов (процедуры и операторы) являются обязательными.
Таблица 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 зависят от других стратегий, как показано в Таблице 3, или от своих собственных стратегий оператора. Для них требуется, чтобы оператор зависимости был определен с типом данных STORAGE в качестве левого аргумента и другим поддерживаемым типом в качестве правого аргумента поддерживаемого оператора. См. определение float4_minmax_ops в качестве примера minmax и box_inclusion_ops в качестве примера inclusion.