BRIN
BRIN (від "Block Range Index") — призначена для обробки дуже великих таблиць, в яких певні стовпці мають деяку природну кореляцію з їх фізичним розташуванням в таблиці. Був запроваджений у версії PostgreSQL 9.5.
Вступ
На відміну від звичного B-tree (бінарного дерева), цей індекс набагато ефективніший для дуже великих таблиць, і в деяких ситуаціях дозволяє замінити собою перебірку. BRIN-індекс має сенс застосовувати для таблиць, в яких частина даних вже за своєю природою якось відсортована. Наприклад, це характерно для логів або для історії замовлень магазину, які пишуться послідовно, а тому вже на фізичному рівні впорядковані за датою / номером, і в той же час такі таблиці з такими даними зазвичай розростаються до гігантських розмірів.
Індекси BRIN можуть задовольняти запити за допомогою регулярних перевірок індексів бітових карт, і повертатимуть всі кортежі на всіх сторінках в межах кожного діапазону, якщо зведена інформація, що зберігається в індексі, узгоджується з умовами запиту. Виконавець запиту відповідає за повторну перевірку цих кортежів і відкидає ті, які не відповідають умовам запиту. Оскільки індекс BRIN має дуже малий розмір, сканування індексу додає невеликі накладні витрати в порівнянні з послідовним скануванням, але може уникнути сканування великих частин таблиці, які, як відомо, не містять співпадаючих кортежів.
Розмір діапазону блоків визначається під час створення індексу параметром сховища pages_per_range. Кількість записів індексу дорівнюватиме розміру відносин на сторінках, ділення на вибране значення для page_per_range. Таким чином, чим менше число, тим більше індекс, але в той же час зберігаються зведені дані можуть бути більш точними, і при індексуванні можна пропускати більше блоків даних.
Вбудовані класи операторів
Конкретні дані, які збережуть індекс BRIN, а також конкретні запити, які індекс зможе задовольнити, залежать від класу оператора, обраного для кожного стовпця індексу. Типи даних, що мають лінійний порядок сортування, можуть мати класи операторів, які зберігають, наприклад, мінімальне і максимальне значення в кожному діапазоні блоків; Геометричні типи можуть зберігати обмежує прямокутник для всіх об'єктів в діапазоні блоків.
Таблиця вбудованих класів операторів
Основний дистрибутив PostgreSQL включає класи операторів BRIN, які показані нижче в таблиці.
Назва | Індексований тип даних | Індексуємі оператори |
---|---|---|
abstime_minmax_ops |
abstime |
< <= = >= > |
int8_minmax_ops |
bigint |
< <= = >= > |
bit_minmax_ops |
bit |
< <= = >= > |
varbit_minmax_ops |
bit varying |
< <= = >= > |
box_inclusion_ops |
box |
<<| |>> |&> |
bytea_minmax_ops |
bytea |
< <= = >= > |
bpchar_minmax_ops |
character |
< <= = >= > |
char_minmax_ops |
"char" |
< <= = >= > |
date_minmax_ops |
date |
< <= = >= > |
float8_minmax_ops |
double precision |
< <= = >= > |
inet_minmax_ops |
inet |
< <= = >= > |
network_inclusion_ops |
inet |
&& >>= <<= = >> << |
int4_minmax_ops |
integer |
< <= = >= > |
interval_minmax_ops |
interval |
< <= = >= > |
macaddr_minmax_ops |
macaddr |
< <= = >= > |
name_minmax_ops |
name |
< <= = >= > |
numeric_minmax_ops |
numeric |
< <= = >= > |
pg_lsn_minmax_ops |
pg_lsn |
< <= = >= > |
oid_minmax_ops |
oid |
< <= = >= > |
range_inclusion_ops |
any range type |
- = < <= = > >= |
float4_minmax_ops |
real |
< <= = >= > |
reltime_minmax_ops |
reltime |
< <= = >= > |
int2_minmax_ops |
smallint |
< <= = >= > |
text_minmax_ops |
text |
< <= = >= > |
tid_minmax_ops |
tid |
< <= = >= > |
timestamp_minmax_ops |
timestamp without time zone |
< <= = >= > |
timestamptz_minmax_ops |
timestamp with time zone |
< <= = >= > |
time_minmax_ops |
time without time zone |
< <= = >= > |
timetz_minmax_ops |
time with time zone |
< <= = >= > |
uuid_minmax_ops |
uuid |
< <= = >= > |
Технічне обслуговування індексів
Під час створення всі скановані сторінки індексу скануються і створюється зведений індексний кортеж для кожного діапазону, включаючи, можливо, неповний діапазон в кінці. Оскільки нові сторінки заповнюються даними, діапазони сторінок, які вже зведені, будуть приводити до оновлення зведеної інформації даними з нових кортежів. Коли створюється нова сторінка, що не потрапляє в останній підсумований діапазон, цей діапазон автоматично не отримує зведений кортеж; Ці кортежі залишаються немаркованими до тих пір, поки наступний цикл ущільнення не викликатиме пізніше, створюючи початкові зведення. Цей процес можна викликати вручну за допомогою функції brin_summarize_new_values (regclass) або автоматично, коли VACUUM обробляє таблицю.
Можливості до розширення
Інтерфейс BRIN має високий рівень абстракції, що вимагає реалізації методу доступу тільки для реалізації семантики типу даних, до якого здійснюється доступ. Рівень BRIN сам піклується про паралелізм, протоколювання і пошук структури індексу. Все, що потрібно для роботи з методом доступу BRIN, - це реалізувати кілька користувальницьких методів, які визначають поведінку зведених значень, що зберігаються в індексі, і то, як вони взаємодіють з ключами сканування. Коротше кажучи, BRIN поєднує розширюваність з загальними принципами, повторне використання коду і чистий інтерфейс.
Існує чотири методи, які операторський клас для BRIN повинен забезпечувати:
1)BrinOpcInfo * opcInfo (Oid type_oid)
Повертає внутрішню інформацію про зведених даних індексованих стовпців. Значення, що повертається повинно вказувати на palloc'd 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 може використовуватися пiдпрограммами класу оператора для передачі інформації між допоміжними процедурами під час сканування індексу.
2)bool consistent(BrinDesc *bdesc, BrinValues *column, ScanKey key)
Повертає, чи узгоджує ScanKey з заданими індексованими значеннями діапазону. Номер атрибута, який слід використовувати, передається як частина ключа сканування.
3)bool addValue(BrinDesc *bdesc, BrinValues *column, Datum newval, bool isnull)
З огляду на індексний кортеж і індексовані значення, змінює вказаний атрибут кортежу так, щоб він додатково представляв нове значення. Якщо будь-яка модифікація була зроблена з кортежем, повертає true.
4)bool unionTuples(BrinDesc *bdesc, BrinValues *a, BrinValues *b)
Консолідація двох індексних кортежів. З урахуванням двох індексних кортежів, він змінює вказаний атрибут першого з них так, що він представляє обидва кортежа. Другий кортеж не змінюється.
Класи операторів, які реалізують абсолютно іншу семантику, також можливі за умови реалізації описаних вище чотирьох основних процедур підтримки. Зверніть увагу, що зворотна сумісність між основними випусками не гарантована: наприклад, в наступних випусках можуть знадобитися додаткові процедури підтримки.
Щоб написати операторний клас для типу даних, який реалізує повністю впорядковану множину, можна використовувати процедури підтримки minmax разом з відповідними операторами, як показано в таблиці нижче.
Член класу оператора | Об'єкт |
---|---|
Support Procedure 1 | внутрішня функція brin_minmax_opcinfo() |
Support Procedure 2 | внутрішня функція brin_minmax_add_value() |
Support Procedure 3 | внутрішня функція brin_minmax_consistent() |
Support Procedure 4 | внутрішня функція brin_minmax_union() |
Operator Strategy 1 | оператор менше-ніж |
Operator Strategy 2 | оператор менше-ніж-або-дорівнює |
Operator Strategy 3 | оператор дорівнює |
Operator Strategy 4 | оператор більше-ніж-або-дорівнює |
Operator Strategy 5 | оператор більше-ніж |