Использование
Эта страница переведена при помощи нейросети GigaChat.
OrioleDB использует встроенный API Table Access Method (метод доступа к таблицам) PostgreSQL. При создании таблицы можно указать USING orioledb;.
Быстрый старт
Запуск PostgreSQL
Расширение OrioleDB требует подключаемого хранилища PostgreSQL. До момента интеграции необходимых патчей сообществом PostgreSQL, для запуска PostgreSQL на локальной машине можно использовать Docker-образ OrioleDB:
docker run -d --name orioledb -p 5432:5432 orioledb/orioledb:latest-pg17
Активация расширения
Для активации расширения OrioleDB выполнить команду:
CREATE EXTENSION orioledb;
Создание таблиц
Рассмотрим определение таблицы blog_post для хранения записей блога с двумя индексами: первичным ключом по колонке id и вторичным ключом по колонке published_at.
-- Создание таблицы
CREATE TABLE blog_post
(
id int8 NOT NULL,
title text NOT NULL,
body text NOT NULL,
author text NOT NULL,
published_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
views bigint NOT NULL,
PRIMARY KEY(id)
) USING orioledb; -- Определение движка хранения
-- Создание индекса
CREATE INDEX blog_post_published_at ON blog_post(published_at);
В OrioleDB применяются индексно-организованные таблицы. Поэтому выбор первичного ключа является критически важным решением, влияющим на производительность. При отсутствии явного указания первичного ключа будет создан скрытый суррогатный первичный ключ на основе виртуальной колонки ctid.
Выполнение запросов к таблицам
К таблицам применяются стандартные DML-запросы, включая SELECT, INSERT, UPDATE, DELETE и INSERT ON CONFLICT.
Пример:
INSERT INTO blog_post (id, title, body, author, views)
VALUES (1, 'Hello, World!', 'This is my first blog post.', 'John Doe', 1000);
SELECT * FROM blog_post ORDER BY published_at DESC LIMIT 10;
Просмотр планов выполнения запросов
Планы запросов с участием таблиц OrioleDB просматриваются с использованием оператора EXPLAIN стандартным образом.
EXPLAIN SELECT * FROM blog_post ORDER BY published_at DESC LIMIT 10;
QUERY PLAN
------------------------------------------------------------------------------------------------------------
Limit (cost=0.15..1.67 rows=10 width=120)
-> Index Scan Backward using blog_post_published_at on blog_post (cost=0.15..48.95 rows=320 width=120)
(2 rows)
EXPLAIN SELECT * FROM blog_post WHERE id = 1;
QUERY PLAN
----------------------------------------------------------------------------------
Index Scan using blog_post_pkey on blog_post (cost=0.15..8.17 rows=1 width=120)
Index Cond: (id = 1)
(2 rows)
Оператор EXPLAIN (ANALYZE, BUFFERS) позволяет просмотреть статистику доступа к страницам.
# EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM blog_post ORDER BY published_at DESC LIMIT 10;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=0.29..0.54 rows=10 width=42) (actual time=0.100..0.210 rows=10 loops=1)
-> Index Scan Backward using blog_post_published_at on blog_post (cost=0.29..251.27 rows=9999 width=42) (actual time=0.097..0.202 rows=10 loops=1)
Planning:
Buffers: shared hit=35
Planning Time: 1.147 ms
Execution Time: 0.284 ms
(6 rows)
Расширенное использование
Использование таблиц OrioleDB по умолчанию
Для того чтобы все создаваемые таблицы автоматически использовали метод доступа orioledb без явного указания его при каждом CREATE TABLE, добавьте в файл конфигурации PostgreSQL: default_table_access_method = 'orioledb'.
Системные каталоги, которые могут быть только типа heap (куча), данной настройке не подлежат. Таблицы, созданные до установки данного параметра, сохраняют предыдущий метод доступа.
Сортировки (Collations)
Таблицы OrioleDB поддерживают только сортировки ICU, C и POSIX. Необходимо убедиться, что кластер или база данных настроены с сортировками по умолчанию из данного перечня; в противном случае потребуется указывать COLLATE для каждой колонки типа text в таблице.
Для сортировок, используемых в колонках и индексах таблиц orioledb, команда ALTER COLLATION REFRESH VERSION также отключена.
Сжатие данных на уровне блоков
В OrioleDB реализовано сжатие на уровне блоков. Уровни сжатия представляются целочисленными значениями от -1 до 22. Значение -1 означает отсутствие сжатия (по умолчанию), значения от 0 до 22 определяют уровни сжатия библиотеки zstd.
Уровень сжатия таблицы контролируется следующими опциями:
compress— уровень сжатия для всех структур данных таблицы (значение-1отключает сжатие для таблицы, отсутствие указания приводит к использованию значенияorioledb.default_compress);primary_compress— уровень сжатия для первичного ключа таблицы (при значении-1наследуется из значенияcompressдля таблицы, если оно положительно, в противном случае используетсяorioledb.default_primary_compress);toast_compress— уровень сжатия для TOAST-значений таблицы (при значении-1наследуется из значенияcompressдля таблицы, если оно положительно, в противном случае используетсяorioledb.default_toast_compress).
Отдельные индексы также имеют опцию compress, которая контролирует уровень сжатия конкретного индекса, переопределяя значение опции compress таблицы.
CREATE TABLE compression_test
(
id int8 NOT NULL,
value1 float8 NOT NULL,
value2 text NOT NULL,
PRIMARY KEY(id)
) USING orioledb
WITH (compress = 5, toast_compress = 10, primary_compress = -1);
CREATE INDEX compression_test_value1_idx ON compression_test(value1)
WITH (compress = 22)
CREATE INDEX compression_test_value2_idx ON compression_test(value2);
В данном примере первичный ключ таблицы compression_test использует сжатие согласно значению orioledb.default_primary_compress, TOAST-значения сжимаются на уровне 10, индекс compression_test_value1_idx сжат на уровне 22, индекс compression_test_value2_idx сжат на уровне 5.
Fillfactor
Таблицы и индексы OrioleDB поддерживают опцию fillfactor, аналогичную опции для таблиц heap (куча) и индексов PostgreSQL документация для таблиц, документация для индексов. Умеренно низкое значение fillfactor ускоряет модификации данных таблицы за счет резервирования дополнительного пространства на диске. Установка данной опции рекомендуется для таблиц с ожидаемо высокой частотой модификаций.
CREATE TABLE o_test_fillfactor
(
f1 text,
f2 varchar,
f3 integer,
PRIMARY KEY(f1)
) USING orioledb WITH (fillfactor = 60);
CREATE INDEX o_test_fillfactor_ix1 ON o_test_fillfactor(f2) WITH (fillfactor = 80);
В таблицах heap (куча) более низкое значение fillfactor преимущественно ускоряет обновления за счет выделения места для HOT-обновленных кортежей и уменьшения блокировок страниц при конкурентных модификациях путем распределения их по большему количеству страниц. В таблицах orioledb страницы не хранят старые версии кортежей и разделены на блоки, поэтому указанные ограничения изначально отсутствуют. Однако ввиду индексно-организованной структуры таблиц, вставка кортежей в OrioleDB осуществляется в конкретные страницы согласно структуре btree (B-дерева). В OrioleDB опция fillfactor ускоряет как вставки, так и обновления за счет уменьшения количества разделений страниц при отсутствии места на листовой странице для размещения новых кортежей. Принцип работы идентичен как для индексов, так и для таблиц.
Изменить fillfactor можно в любой момент:
ALTER TABLE o_test_fillfactor SET (fillfactor = 20);
ALTER INDEX o_test_fillfactor_ix1 SET (fillfactor = 50);
Кэширование последовательностей
OrioleDB оптимизирует производительность за счет обхода механизма назначения идентификаторов транзакций PostgreSQL (XID) и журнала предзаписи (WAL) для кучи при операциях, строго ограниченных таблицами OrioleDB. Однако, поскольку последовательности PostgreSQL реализованы как отношения heap (куча), вызов nextval() приводит к модификации структур кучи. Это вызывает назначение полного XID PostgreSQL, что нивелирует оптимизации транзакций OrioleDB.
Для предотвращения ненужных назначений XID при использовании колонок на основе последовательностей, необходимо настроить последовательности со значением CACHE:
CREATE SEQUENCE my_seq CACHE 100;
При включенном кэшировании только первоначальный вызов nextval() требует модификации heap (кучи) и назначения XID для получения блока значений. Последующие вызовы в рамках той же сессии извлекают значения из оперативной памяти, сохраняя оптимизированную обработку транзакций OrioleDB.
Данная оптимизация критически важна для рабочих нагрузок с большим объемом мелких транзакций. Для крупных транзакций потеря производительности пренебрежимо мала, поскольку стоимость назначения XID значительно амортизируется.
Расчет размера журнала отката (undo log)
OrioleDB хранит часть данных модификаций во временных журналах отката (Undo logs). Хотя данное хранилище, разделенное от файлов отношений, является более удобным и не подвержено разрастанию, функции PostgreSQL для определения размера таблиц и баз данных не учитывают размер журналов отката. Для учета временных данных, связанных с Undo, использовать специальную функцию:
SELECT * FROM orioledb_undo_size();
Данные Undo подсчитываются по трем категориям: системный undo, пользовательский undo на уровне страниц и пользовательский undo на уровне строк.
Проверка целостности таблиц
Функция verify_orioledb() проверяет все B-деревья (первичные, вторичные, TOAST, мостовые) отношения OrioleDB и возвращает по одной строке на каждый индекс, не прошедший проверку. Пустой результат означает исправность отношения.
SELECT * FROM verify_orioledb('blog_post'::regclass);
-- thorough_check = true также проверяет карту свободного пространства на диске
SELECT * FROM verify_orioledb('blog_post'::regclass, true);
Функция захватывает только блокировку AccessShareLock, поэтому конкурентные чтения и записи не блокируются. При выполнении контрольной точки функция ожидает ее завершения на затронутом дереве, а не возвращает ложное сообщение об ошибке.
Функция verify_orioledb() также интегрирована в механизм amcheck PostgreSQL, поэтому отношения OrioleDB проверяются утилитой pg_amcheck совместно с отношениями кучи:
pg_amcheck -d mydb -t public.blog_post
pg_amcheck -d mydb # все проверяемые отношения в базе данных
Удаление данных
В OrioleDB разреженные страницы автоматически объединяются. Поэтому при удалении большого количества строк страницы данных освобождаются и становятся доступными для дальнейшего использования. Файлы данных в данной ситуации в настоящее время не уменьшаются, однако данная функциональность будет реализована в ближайшее время.
Контрольные точки, WAL и восстановление
В OrioleDB имеется собственный механизм восстановления: контрольные точки с копированием при записи (copy-on-write) и WAL на уровне строк. Однако как контрольные точки, так и WAL OrioleDB интегрированы в PostgreSQL. Процесс checkpointer (контрольных точек) PostgreSQL обслуживает также таблицы OrioleDB. Поток WAL PostgreSQL содержит как записи WAL встроенных таблиц PostgreSQL, так и записи WAL на уровне строк таблиц OrioleDB.
Восстановление с использованием записей WAL на уровне строк может требовать значительных ресурсов процессора. Поэтому реализовано параллельное восстановление таблиц OrioleDB. OrioleDB запускает собственный пул потоков восстановления, каждый из которых отвечает за повторное выполнение определенной части записей WAL.
В OrioleDB имеется собственный пул фоновых процессов записи (размер пула определяется параметром GUC orioledb.bgwriter_num_workers). Использование нескольких фоновых процессов записи повышает эффективность использования дискового ввода-вывода на современном оборудовании.
Экспериментальная поддержка блочных устройств
В OrioleDB реализована экспериментальная поддержка режима прямого взаимодействия с блочными устройствами. Данный режим устраняет накладные расходы файловой системы.
В данном режиме основная часть данных таблицы хранится в файловой системе, однако небольшие объемы метаданных по-прежнему хранятся в каталоге данных.
Текущая реализация поддержки блочных устройств содержит утечки памяти, приводящие к сообщению об ошибке device file overflow (переполнение файла устройства), даже если фактический размер данных значительно меньше размера блочного устройства. В данном случае помогает только повторная инициализация каталога данных.
В ближайших планах — исправление утечек памяти и разработка инструментов для мониторинга свободного пространства блочного устройства.
Для активации режима блочного устройства необходимо указать параметры GUC orioledb.device_filename и orioledb.device_length. При включении параметра GUC orioledb.use_mmap блочное устройство подключается через mmap. Данный режим оптимален для NVRAM, подключенной напрямую к шине данных. Режим mmap не рекомендуется для обычных устройств, так как текущая реализация mmap в Linux имеет серьезные проблемы конкурентности.
Экспериментальная поддержка индексов, отличных от btree
В OrioleDB реализована экспериментальная поддержка индексов, отличных от btree. Данная функциональность обеспечивается внутренним «мостовым индексом» (bridge index) между индексом, не являющимся btree, и таблицей OrioleDB. Мостовой индекс автоматически добавляется при построении первого индекса, не являющегося btree.
CREATE INDEX blog_post_title_gin_idx ON blog_post USING GIN (title);
Явное построение мостового индекса для таблицы не является обязательным, однако возможно:
ALTER TABLE blog_post SET (index_bridging);
При удалении всех существующих мостовых индексов для таблицы «мостовой индекс» не удаляется автоматически. Если добавление индексов, отличных от btree, в дальнейшем не планируется, можно удалить ненужный «мостовой индекс» для данной таблицы:
ALTER TABLE blog_post RESET (index_bridging);
Индекс btree также может быть построен как мостовой индекс (использовать только для тестовых целей, не рекомендуется):
CREATE INDEX blog_post_title_idx ON blog_post USING btree(title) with (orioledb_index = off);
Текущие ограничения
В настоящее время OrioleDB находится на стадии разработки. Следовательно, существуют следующие временные ограничения:
-
Утилита
pg_rewindкопирует таблицы OrioleDB полностью. В ближайшее время в OrioleDB будет реализовано инкрементальное копирование таблиц с использованиемpg_rewind. -
OrioleDB поддерживает параллельное последовательное сканирование, но не поддерживает другие типы сканирования.
-
OrioleDB не поддерживает подготовленные транзакции (prepared transactions).
-
Поддержка индексов, отличных от btree, в OrioleDB является экспериментальной.
-
OrioleDB поддерживает битовое сканирование только для первичных ключей типов int4, int8 и ctid.
-
Конкурентность на уровне строк в OrioleDB имеет некоторые отличия.
-
Команды
CLUSTERиVACUUM FULLв OrioleDB пока не поддерживаются, так как не реализовано переписывание таблиц для этих команд. Кроме того, командаCLUSTERне имеет существенного смысла для индексно-организованных таблиц. -
Команда
REINDEX CONCURRENTLYв настоящее время не поддерживается. -
Таблицы OrioleDB пока не поддерживают выборочное сканирование (
Sample Scans). -
В OrioleDB не реализована истинная сериализуемая изоляция снимков (SERIALIZABLE Snapshot Isolation). Параметр GUC
orioledb.serializableконтролирует обработку транзакций SERIALIZABLE:table_lock(по умолчанию): каждое отношение, с которым взаимодействует транзакция SERIALIZABLE, защищается грубозернистой тяжелой блокировкойExclusiveLock. Корректный, но пессимистичный подход — конкурентные непротиворечивые рабочие нагрузки деградируют до последовательного выполнения.error: отклонение транзакций SERIALIZABLE с кодом ошибкиERRCODE_FEATURE_NOT_SUPPORTED(устаревшее поведение).repeatable_read: обработка SERIALIZABLE какREPEATABLE READтолько для таблиц OrioleDB — дополнительные блокировки не захватываются, снимок CSN OrioleDB уже обеспечивает стабильные чтения в рамках транзакции. Таблицы кучи в той же транзакции продолжают использовать SSI PostgreSQL стандартным образом.
-
Обратное извлечение данных из курсора поддерживается только при объявлении курсора с ключевым словом
SCROLL. -
В OrioleDB не используются контрольные суммы на страницах данных, поэтому инициализация кластера базы данных с флагом
-k(--data-checksums) не имеет эффекта для таблиц OrioleDB. -
Последовательности PostgreSQL опираются на отношения кучи. Обращение к ним (например, через
nextval()) вызывает назначение полного идентификатора транзакции PostgreSQL (XID), обходя оптимизированные механизмы транзакций OrioleDB, если не используется кэширование последовательностей.
Ссылки
Дополнительную информацию смотрите в разделах: «Настройка», «Разделенное хранение и вычисления» и «Откат на основе журнала отката (Undo-based Rewind)».