Хранение NoSQL данных
в Oracle и PostgreSQL
Аркаев Андрей
Чем занимаемся
Naumen Contact Center
→ Звонок (вх/исх)
→ Распределение на оператора
→ Заполнение анкеты
→ Сохранение в БД
→ Отчёты
Анкета
Наши требования

3 млн звонков с анкетами в сутки

20 атрибутов на каждую анкету

сложная иерархия форм анкеты
(сотни разных анкет и форм)

PostgreSQL, Oracle >= 10g

Скорость открытия 2с

1000 операторов
Хранение атрибутов в отдельной таблице
anketa:

id

card_id

creationDate

…
attr_card:

card_id
attr:

card_id

property_id

str_value1

str_value2

date_value

dbl_value

int_value

clob_value
Хранение атрибутов в отдельной таблице
anketa:

id

other_value

creationDate

…
attr:

ank_id
(→anketa.id)

property_id

str_value1

str_value2

date_value

dbl_value

int_value

clob_value
Плюсы и минусы
+ схема данных
фиксирована
+ можно
использовать для
разных классов
- много данных
- сложно
партиционировать
- значения хранятся
в конкретном виде
- много null-
значений
- большие индексы
Хранение атрибутов столбцами
anketa:

Id

creationDate

...

NewAttr1

NewAttr2

NewAttr3

...
anketa:

id

...

NewAttr5000

...
Хранение атрибутов столбцами
anketa:

Id

creationDate

...

NewAttr1
anketa_type1

obj_id
(->anketa.id)

NewAttr2

NewAttr3
anketa_type2

obj_id
(->anketa.id)

NewAttr4

NewAttr5
Плюсы и минусы
+ любой тип
данных
+ индексы на
нужные столбцы
+ партицион-е
- ограничено
количество атрибутов
- тяжелое удаление
- неудобные запросы
- блокировки схемы
Что использовать

PostgreSQL >= 9.4 : json или jsonb

Oracle >=10g : xmltype (clob)

Oracle 11g : xmltype (binary xml)

MsSQL 2014 : xml

MySQL : -
JSON
{ "form1": {
"nickname": "Superman",
"name": "Кларк Кент",
"alias": [ "Человек из стали",
"Последний сын Криптона",
"Человек завтрашнего дня" ],
"height": 190,
"weight": 106,
"alien": true
}, … }
Получение в PostgreSQL
Создание столбца:
alter table test_table
add column attrData jsonb;
Получение значения:
SELECT attrData->’form3’->>’title’
FROM test_table
XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
<form1>
<nickname>Superman</nickname>
<name>Кларк Кент</name>
<alias>Человек из стали</alias>
<alias>Последний сын Криптона</alias>
<alias>Человек завтрашнего дня</alias>
<height>190</height>
<weight>106</weight>
<alien>true</alien>
</form1> ...
Получение в Oracle
Создание столбца:
alter table test_table
add column attrData xmltype;
Получение значения:
SELECT
extractValue(jsonData,'/root/form3/title'),
extract(jsonData,'...').getStringVal(),
extract(jsonData,'...').getNumVal(),
extract(jsonData,'...').getClobVal()
FROM test_table
Плюсы и минусы
+ не нужны join
+ любое
количество
атрибутов
+ удобнее
получать значения
ч/з SQL
+ история
+ партицион-е
- разный синтаксис у
разных БД
- тип данных: строка
- нет FK
- Oracle 4Кб
Получение массивов в PostgreSQL
SELECT attrData→'form1'→'alias'
FROM test_table

["Человек из стали", "Последний сын
Криптона", "Человек завтрашнего дня"]
Получение массивов в Oracle
select alias.COLUMN_VALUE
FROM test_table, TABLE( XMLSequence(
extract(attrData, '/root/form1/alias'))) alias

"Человек из стали"

"Последний сын Криптона"

"Человек завтрашнего дня"
Индексы
PostgreSQL

Gin-индекс
Oracle

ctxsys.ctxxpath

XMLIndex (Oracle 11g)
Индекс в PostgreSQL
CREATE INDEX idxginp ON test_table
USING gin (attrData jsonb_path_ops)
SELECT * FROM test_table
WHERE attrData @>
'{"form1": { "nickname" : "Superman"}}'
Индекс в Oracle
CREATE INDEX idx_attrdata ON
test_table(attrData)
indextype is ctxsys.ctxxpath
SELECT * FROM test_table WHERE
existsNode(attrData,
'/root/form1/nickname="Superman"')=1
Результаты PostgreSQL
После
До
0 10 20 30 40 50 60 70
Индексы
Атрибуты
Анкета
Результаты Oracle
После 11g
После
До
0 10 20 30 40 50 60 70
Индексы
Атрибуты
Анкета
Итоги перехода
1. Быстрая выборка и обновление
2. Скорость выборки 1.6c → 0.35c
3. Меньшая деградация скорости БД
4. Ускорение импорта в 3 раза
5. Снижение нагрузки на CPU и
требования к железу
6. Уменьшение размера БД
7. “Человеческий” формат данных
Планы на будущее
1. Партиционирование
2. Шардинг
3. Возможность перейти на честные
NoSQL БД
The end
Спасибо!
Вопросы?
Аркаев Андрей
aarkaev@naumen.ru

Использование json/xml в БД PostgreSQL и Oracle для хранения произвольных атрибутов, Андрей Аркаев, Naumen