F.50. pgpro_sfile — хранилище больших объектов #
Модуль pgpro_sfile
позволяет хранить множество больших объектов и предоставляет функциональность, аналогичную большим объектам (LOB) в Oracle. В этом модуле реализован механизм хранения больших объектов в наборе таблиц, управляемых модулем. Каждый объект состоит из порций, или блоков. Блоки разбиты на страницы размером по ~8 КБ. Максимальное количество объектов, блоков и размер объекта в байтах ограничены размером типа bigint
(2^63 - 1). Большой объект pgpro_sfile называется объектом sfile
.
F.50.1. Механизм хранения #
Объекты sfile
хранятся в таблицах, которые создаются модулем pgpro_sfile и находятся под его контролем. В обычных таблицах хранится только идентификатор каждого объекта sfile
в виде ссылки на таблицы, созданные модулем. Как только объект sfile
создан, его можно загружать, читать, опустошать или удалять. При этом данные операции не влияют на обычные таблицы, в которых объект используется.
Механизм хранения представляет собой набор следующих таблиц хранения:
SF_DESCRIPTOR
— реестр, в котором хранятся дескрипторы всех объектовsfile
.SF_PARTITION
— реестр таблиц хранения (секций). Хранит информацию о таблицахSF_PAGE_XX
.SF_BLOCK
— реестр блоков объектовsfile
. Каждый блок может включать несколько страниц объектовsfile
.SF_PAGE_XX
— таблицы со страницами данных объектовsfile
.SF_OPTION
— таблица с параметрами объектовsfile
. На данный момент существует только параметрTABLESPACE
, который позволяет указать табличное пространство для хранения объектовsfile
.
Все таблицы, кроме SF_OPTION
, созданы в специальной схеме pgpro_sfile_data
. Таблица SF_OPTION
создаётся в ходе установки pgpro_sfile. Таблицы SF_DESCRIPTOR
, SF_PARTITION
и SF_BLOCK
создаются в ходе инициализации pgpro_sfile, а таблицы SF_PAGE_XX
создаются, когда объекты sfile
записываются в базу данных, и отслеживаются в реестре SF_PARTITION
.
В следующих разделах описана структура таблиц хранения.
F.50.1.1. SF_OPTION
#
Таблица SF_OPTION
содержит следующие поля:
opt_type | smallint | Значение параметра: GLOBAL = 0, TABLE = 1 или OBJECT = 2. На данный момент поддерживается только значение GLOBAL . |
opt_name | name | Уникальное имя параметра. |
opt_value | name | Значение параметра. |
F.50.1.2. SF_DESCRIPTOR
#
Таблица SF_DESCRIPTOR
содержит следующие поля:
sf_id | bigint | Уникальный идентификатор объекта sfile . |
sf_name | name | Имя объекта sfile . |
sf_persistence | smallint | Тип хранения объекта sfile : RELPERSISTENCE_PERMANENT ="p" или RELPERSISTENCE_UNLOGGED ="u". |
sf_state | smallint | Набор битов, показывающих состояние объекта sfile . Например: SF_STATE_DELETED =1. |
sys_creation_date | timestamp | Дата и время создания объекта sfile . |
sys_update_date | timestamp | Дата и время последнего обновления объекта sfile . |
sf_json_opts | text | Параметры объекта sfile в виде текста или в формате JSON. |
sf_type | text | Тип объекта sfile , заданный вручную. |
tbs_identity | text | Имя табличного пространства для хранения объекта sfile . |
F.50.1.3. SF_PARTITION
#
Таблица SF_PARTITION
содержит следующие поля:
part_id | int | Уникальный идентификатор секции. |
part_data_size | bigint | Число блоков, на данный момент хранящихся в секции. |
part_persistence | smallint | Тип хранения данных в секции: RELPERSISTENCE_PERMANENT ="p" или RELPERSISTENCE_UNLOGGED ="u". |
rel_identity | text | Имя таблицы, в которой хранятся данные секции. |
tbs_identity | text | Имя табличного пространства, в котором хранятся данные секции. |
F.50.1.4. SF_BLOCK
#
Таблица SF_BLOCK
содержит следующие поля:
sf_id | bigint | Уникальный идентификатор объекта sfile . |
block_id | bigint | Уникальный идентификатор блока в объекте sfile . Сюда записывается значение аргумента a_sf_index функции sf_write. |
part_id | int | Идентификатор секции, в которой хранятся данные блока. |
block_size | int | Размер блока, в байтах. |
block_start_page | int | Порядковый номер первой страницы блока; нумерация блоков начинается с 1. |
block_end_page | int | Порядковый номер последней страницы блока; нумерация блоков начинается с 1. |
sys_creation_date | timestamp | Дата и время создания блока. |
sys_update_date | timestamp | Дата и время последнего обновления блока. |
F.50.1.5. SF_PAGE_XX
#
Каждая таблица SF_PAGE_XX
содержит следующие поля:
sf_id | bigint | Уникальный идентификатор объекта sfile . |
block_id | bigint | Уникальный идентификатор блока, в котором находится страница. |
page_no | int | Порядковый номер страницы в блоке. |
data | bytea | Буфер для хранения данных объекта sfile . Максимальный объём данных для хранения в буфере — 8096 байт. |
F.50.2. Установка #
Расширение pgpro_sfile
входит в состав Postgres Pro Enterprise. Чтобы его задействовать, создайте расширение следующим запросом:
CREATE EXTENSION pgpro_sfile;
F.50.3. Функции #
Функции pg_superfile позволяют выполнять различные операции с объектами sfile
, такие, как создание, запись, чтение, удаление и многое другое. Для доступа к идентификаторам объектов sfile
эти функции используют тип данных sfile
. Для хранения идентификаторов в таблицу необходимо добавить новый столбец с типом данных sfile
.
-
sf_initialize()
returnsvoid
# Инициализирует хранилище объектов
sfile
. Эта функция создаёт сначала схемуpgpro_sfile_data
, а затем — необходимые таблицы и последовательности в ней. Вызовите эту функцию сразу после установки расширения.-
sf_deinitialize()
returnsvoid
# Каскадно удаляет схему
pgpro_sfile_data
. Вызовите эту функцию перед удалением расширения, чтобы удалить все данные объектовsfile
.-
sf_create(
returnsa_sf_name
text
,a_sf_persistence
text
,a_sf_json_options
text
[,a_sf_tablespace
text
])sfile
# Создаёт новый объект
sfile
с именемa_sf_name
и возвращает его идентификатор. Объект будет журналируемым или нежурналируемым в зависимости от значения параметраa_sf_persistence
:LOGGED
илиUNLOGGED
. Аргументa_sf_json_options
должен содержать файл JSON параметрами. Аргументa_sf_tablespace
позволяет указать табличное пространство, в котором будет храниться объектsfile
. Если значение не задано, используется табличное пространство по умолчанию.Добавляет в отношение SF_DESCRIPTOR дескриптор объекта
sfile
с нулевым размером. Поэтому для только что созданного объекта вызов функций sf_is_empty и sf_is_valid вернёт значениеTRUE
. Блоки и секции функциейsf_create
не создаются.-
sf_create_empty([
#a_sf_tablespace
text
]) returnssfile
Создаёт новый пустой объект
sfile
с автоматически сгенерированным именем (sf_gen_XX
) и пустым списком параметров и возвращает идентификатор объекта. Аргументa_sf_tablespace
позволяет указать табличное пространство, в котором будет храниться объектsfile
. Если оно не указано, используется табличное пространство по умолчанию.-
sf_write(
returnsa_sf
sfile
,a_sf_data
bytea
[,a_sf_index
bigint
])integer
# Вставляет новый блок данных
a_sf_data
с индексом, указанным в аргументеa_sf_index
, в объектsfile
, идентификатор которого указывается параметромa_sf
. Возвращает количество добавленных байтов. В качестве индекса по умолчанию используется текущая временная метка.Функция сначала проверяет, был ли уже записан объект
sfile
, чтобы выяснить, доступна ли таблица секций SF_PAGE_XX и достаточно ли в ней свободного места для записи блока. Если подходящая секция в таблице не находится или это первая операция записи, проверяются все остальные секции, после чего первая доступная секция блокируется для записи. Если таковая не находится, создаётся новая и добавляется в реестр SF_PARTITION. Затем в SF_BLOCK инициализируется новая запись для блока, блок разбивается на страницы размером ~8 КБ, и эти страницы записываются в ранее заблокированную секциюPG_PAGE_XX
. Когда блок записан, в полеpart_data_size
таблицыSF_PARTITION
корректируется размер данных.-
sf_read(
returnsa_sf
sfile
[,a_offset
bigint
,a_length
integer
])bytea
# Считывает число байтов, указанное в параметре
a_length
, из объектаsfile
, определённого его идентификаторомa_sf
. Чтение выполняется со смещением, заданным в аргументеa_offset
. Можно считать только до ~1 ГБ данных, что является ограничением типаvarlena
. Значение по умолчанию: ~1 ГБ. Смещение по умолчанию: 0. Возвращает буфер с прочитанными данными.-
sf_size(
returnsa_sf
sfile
)bigint
# Получает размер объекта
sfile
.-
sf_truncate(
returnsa_sf
sfile
)bigint
# Опустошает объект
sfile
: удаляет все данные, но оставляет нетронутым сам объект и возвращает новый размер объектаsfile
, то есть 0. Поэтому при последующем вызове функций sf_is_valid и sf_is_empty для этого объекта возвращается значениеTRUE
.-
sf_delete(
returnsa_sf
sfile
)bigint
# Удаляет объект
sfile
и возвращает объём удалённых данных. Функция удаляет все блоки данных, а затем удаляет дескриптор объекта из SF_DESCRIPTOR. После этого объект становится недоступен, поэтому при вызове функции sf_is_valid для этого объекта возвращается значениеFALSE
.-
sf_describe(
returnsa_sf
sfile
)cstring
# Получает данные дескриптора объекта
sfile
и возвращает их в виде текста.-
sf_get_json_options(
returnsa_sf
sfile
)cstring
# Получает файл JSON с параметрами, заданными при создании объекта
sfile
(см. статью sf_create).-
sf_find(
returnsa_sf_name
text
)sfile
# Ищет объект
sfile
по указанному имени и возвращает его идентификатор.-
sf_set_option(
returnsa_opt_name
text
, [a_opt_value
text
,a_opt_type
text
])void
# Задаёт параметр (настройку модуля pgpro_sfile), указанный аргументом
a_opt_name
, в таблице SF_OPTION. На данный момент поддерживаются только значенияTABLESPACE
для параметраa_opt_name
иGLOBAL
дляa_opt_type
. Значение по умолчанию дляa_opt_value
: NULL. Значение по умолчанию дляa_opt_type
:GLOBAL
. С параметромTABLESPACE
модуль pgpro_sfile проверяет, существует ли указанное табличное пространство, и если нет, то выдаёт ошибку.-
sf_get_option(
returnsa_opt_name
text
)cstring
# Получает параметр модуля pgpro_sfile с указанным в SF_OPTION именем.
-
sf_delete_option(
returnsa_opt_name
text
)void
# Удаляет параметр модуля pgpro_sfile с указанным в SF_OPTION именем.
-
sf_is_valid(
returnsa_sf
sfile
)bool
# Возвращает значение
TRUE
, если в аргументе указан существующий объектsfile
, и значениеFALSE
в противном случае.-
sf_is_empty(
returnsa_sf
sfile
)bool
# Возвращает значение
TRUE
, если в аргументе указан существующий пустой объектsfile
, и значениеFALSE
в противном случае.-
sf_is_logged(
returnsa_sf
sfile
)bool
# Возвращает значение
TRUE
, если в аргументе указан журналируемый (постоянный) объектsfile
, и значениеFALSE
в противном случае.-
sf_trim(
returnsa_sf
sfile
,a_length
bigint
)bigint
# Усекает объект
sfile
, указанный аргументомa_sf
, до размера, заданного аргументомa_length
. Усечённые данные удаляются. Возвращается обновлённый размер объекта. Если размер объекта меньше, чемa_length
, возвращается фактический размер объекта.-
sf_set_type(
returnsa_sf
sfile
,a_type
text
)void
# Задаёт для объекта
sfile
, заданного параметромa_sf
, пользовательский тип, указанный в аргументеa_type
.-
sf_get_type(
returnsa_sf
sfile
)cstring
# Получает пользовательский тип указанного объекта
sfile
в виде текста.-
sf_md5(
returnsa_sf
sfile
)text
# Вычисляет MD5-хеш для указанного объекта
sfile
.
F.50.4. Параллельная обработка #
Для ускорения взаимодействия с большими объектами, функции чтения sf_read и sf_size и функция записи sf_write могут выполняться параллельно. Эти функции накладывают на объект sfile
блокировку типа AccessShareLock
, что не запрещает чтение объекта. Функции sf_read
и sf_size
снимают эту блокировку после выполнения операции, в то время как функция записи sf_write
сохраняет её до завершения транзакции, чтобы предотвратить удаление, опустошение, усечение объекта до завершения транзакции. Изменения в таблицах SF_BLOCK и SF_PAGE_XX, внесённые функцией записи sf_write
, не видны в параллельном сеансе, и если блокировка AccessShareLock
снимается до конца транзакции, то объект sfile
может быть удалён в другом сеансе, который не знает о записях, добавленных в таблицы SF_BLOCK
и SF_PAGE_XX
. В итоге объект sfile
будет удалён, а добавленные записи останутся.
В блоки одного объекта может идти запись из разных сеансов, а последовательность записи блоков зависит от времени вызова sf_write
. Для управления последовательностью записи блоков используется значение аргумента a_sf_index
, а если он не передан, используется значение по умолчанию: временная метка вызова функции. Каждый вызов sf_write
накладывает блокировку AccessExclusiveLock
на секции, куда записываются блоки, что запрещает запись в блоки одной и той же секции из разных сеансов, поскольку невозможно одновременно менять поле part_data_size
таблицы SF_PARTITION. При этом запись блоков объекта sfile
из нескольких сеансов в разные секции разрешается.
Функции sf_trim, sf_truncate и sf_delete нельзя выполнять параллельно, поскольку они накладывают блокировку AccessExclusiveLock
на объект sfile
.
F.50.5. Пример #
Пример использования модуля pgpro_sfile:
-- Создание расширения pgpro_sfile CREATE EXTENSION pgpro_sfile; -- Инициализация хранилища объектов sfile SELECT sf_initialize(); -- Создание тестовой таблицы CREATE TABLE test_sfile (id int, l sfile); -- Создание и сохранение объекта sfile INSERT INTO test_sfile VALUES (1, sf_create('sf', 'LOGGED', NULL)); -- Запись данных в объект sfile и их проверка SELECT sf_write(t.l, '1234567890'::bytea) FROM test_sfile t WHERE id = 1; SELECT encode(b, 'escape'), length(b) FROM (SELECT sf_read(t.l, 0, NULL) b FROM test_sfile t WHERE id = 1) x; -- Усечение объекта sfile и его проверка SELECT sf_trim(t.l, 5) FROM test_sfile t WHERE id = 1; SELECT encode(b, 'escape'), length(b) FROM (SELECT sf_read(t.l, 0, NULL) b FROM test_sfile t WHERE id = 1) x; -- Удаление таблицы DROP TABLE test_sfile; -- Удаление данных из всех объектов sfile SET client_min_messages = WARNING; SELECT sf_deinitialize(); RESET client_min_messages; -- Удаление расширения pgpro_sfile DROP EXTENSION pgpro_sfile;
По завершении работы скрипта выдаётся результат:
CREATE EXTENSION sf_initialize --------------- (1 row) CREATE TABLE INSERT 0 1 sf_write ---------- 10 (1 row) encode | length ------------+-------- 1234567890 | 10 (1 row) sf_trim --------- 5 (1 row) encode | length --------+-------- 12345 | 5 (1 row) DROP TABLE SET sf_deinitialize ----------------- (1 row)
F.50.6. Авторы #
Postgres Professional, Москва, Россия