ZSON: розширення PostgreSQL для прозорого стиснення JSONB



Нещодавно ми виклали на GitHub ZSON. ZSON — це розширення до PostgreSQL для прозорого стиснення JSONB-документів. Стиснення здійснюється шляхом виділення рядків, найбільш часто зустрічаються в ваших документах, і побудови словника з цими рядками. Притому рядки можуть бути не тільки ключами документа, але і значеннями або, наприклад, рядками з вкладених масивів. У деяких випадках ZSON дозволяє зменшити розмір бази до двох разів і збільшити кількість транзакцій в секунду на 10%. У shared buffers документи зберігаються в стислому вигляді, за рахунок чого економиться пам'ять теж.

Цікаво? Читайте далі, і ви дізнаєтеся, як користуватися всім цим господарством на практиці.

Зауваження
Перш, ніж перейти до основного вмісту статті, хочеться відзначити кілька моментів:

  • Бенчмарк ZSON'а в цій статті не наводиться. Зацікавлені читачі можуть ознайомитися з ним тут. Прийміть до уваги, що на практиці все дуже сильно залежить від ваших даних, конфігурації, заліза, версії СУБД і інших факторів. Не вірте синтетичним бенчмарками, перевіряйте всі самостійно!

  • Питання написання розширень для PostgreSQL виходить за рамки цієї статті. Зацікавлені читачі можуть ознайомитися з окремою статтею з даної теми, і далі по посиланнях. Тому, як ZSON працює всередині, якщо це комусь цікаво, я можу присвятити окрему статтю.

  • PostgreSQL має вбудований алгоритм стиснення — PGLZ. ZSON не замінює, а доповнює його. PGLZ стискає кожен документ окремо. Він не може виявити, що в різних документах зустрічаються одні і ті ж рядки. ZSON знаходить ці рядки і замінює їх на 16-бітові коди. Потім документи стискуються PGLZ, як звичайно (або не стискуються, якщо підсумковий документ маленький і/або не тулиться).
Установка
Збірка ZSON з вихідних і його установка здійснюються так:

git clone https://github.com/afiskon/zson.git
cd zson
sudo make install

Після установки проженіть тести:

make installcheck

Увімкніть ZSON для вашої бази даних:

create extension zson;

Вітаю, ZSON встановлений!

Видалити
Коли і якщо ви захочете видалити ZSON, просто вимкніть його:

drop extension zson;

А потім зовсім випиляєте з PostgreSQL:

sudo make uninstall

Всі створені ZSON'ом типи, таблиці і так далі, будуть вичищені автоматично.

Використання
Першим ділом ви повинні навчити ZSON на ваших типових документах. В результаті навчання будується словник з найбільш часто зустрічаються в ваших документах рядками, який потім використовується для стиснення. Навчання відбувається за допомогою наступної процедури:


zson_learn(
tables_and_columns text[][],
max_examples int default 10000,
min_length int default 2,
max_length int default 128,
min_count int default 2
)

Наприклад:

select zson_learn('{{"table1", "row1"}, {"table2", "row2"}}');

Подивитися отриманий в результаті словник можна так:

select * from zson_dict;

Тепер ви можете використовувати ZSON, як прозору заміну типу JSONB:

zson_test=# create table zson_example(x zson);
CREATE TABLE

zson_test=# insert into zson_example values ('{"aaa": 123}');
INSERT 0 1

zson_test=# select x -> 'aaa' from zson_example;
-[ RECORD 1 ]-
?column? | 123

Всі оператори і процедури будуть працювати з ZSON точно так само, як і з JSONB.

Міграція на новий словник
По мірі зміни схеми ваших документів стиснення може стати неефективним через зникнення одних рядків і появи інших. У цьому випадку ви можете перенавчити ZSON на нових даних:

select zson_learn('{{"table1", "row1"}, {"table2", "row2"}}');

При цьому створюється нова версія словника. При відновленні та створенні нових документів вони будуть стискуватися з його допомогою. Старі документи будуть розширюватись за допомогою тієї версії словника, з якою вони були стиснуті. Зверніть увагу, що словники зберігається в пам'яті. Тому ZSON дізнається про новому словнику не відразу, а приблизно через хвилину після його створення.

Визначити, за допомогою якої версії словника був стиснутий конкретний документ, можна за допомогою процедури zson_info:

zson_test=# select zson_info(x) from test_compress where id = 1;
-[ RECORD 1 ]---------------------------------------------------
zson_info | zson version = 0, dict version = 1, ...

zson_test=# select zson_info(x) from test_compress where id = 2;
-[ RECORD 1 ]---------------------------------------------------
zson_info | zson version = 0, dict version = 0, ...

Якщо ви абсолютно впевнені, документи у вашій базі стиснуті з допомогою нової версії словника, ви можете безпечно видалити старий словник:

delete from zson_dict where dict_id = 0;

На практиці, втім, в цьому мало сенсу. Ви заощадите лише пару кілобайт місця на диску. Параноїк всередині мене вважає, що ризик втратити дані за маааленькой неуважність того не варто.

Як зрозуміти, що потрібно оновити словник?
На жаль, важко рекомендувати універсальний підхід. Наприклад, ви можете час від часу перевіряти середній розмір документа у вашій базі:

select pg_table_size('tt') / (select count(*) from tt)

Якщо він став збільшуватися, значить прийшов час оновити словник. Ще можна переучувати ZSON просто час від часу, наприклад, раз в рік.

Нарешті, розробники додатків самі знають, коли вони сильно змінюють схему документів. Можна включити перенавчання ZSON в міграційні скрипти або інструкцію по оновленню програми.

При сильному бажанні можна придумати й інші підходи. Загалом, все сильно залежить від ситуації.

Висновок
Як бачите, завдяки ZSON ви отримуєте найкраще з двох світів — гнучкість schemaless даних, поєднану з компактністю реляційної моделі. При цьому на стороні додатки взагалі нічого не треба робити, все відбувається прозоро, на стороні самої СУБД.

Якщо у вас є питання, я буду радий відповісти на них у коментарях. Будь фідбек, а також pull requests гаряче вітаються.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.