2️⃣ Вертикальное (EAV)
Каждое свойство - это одна строка. Строка содержит: ссылку на родительскую сущность, ссылку на бизнесовый тип поля и само значение.
— справочник типов бизнес-полей
create table client_data_field(
field_id number(10) not null,
field_name varchar2(100 char) not null
);
insert into client_data_field values(1, 'FIRST_NAME');
insert into client_data_field values(2, 'LAST_NAME');
insert into client_data_field values(3, 'MIDDLE_NAME');
insert into client_data_field values(4, 'BIRTH_DAY');
create table client_data_v(
client_id number(38) not null,
field_id number(10) not null,
field_value varchar2(1000 char) not null
);
insert into client_data_v values(777, 1, 'Иван');
insert into client_data_v values(777, 2, 'Иванов');
insert into client_data_v values(777, 4, to_char(date'1984-01-21','dd.mm.yyyy'));
Для поиска индексируются поля field_value, field_id.
Если нужен поиск по нескольким свойствам, придется писать join для каждого критерия.
Например поиск по last_name + др:
select ...
from client_data bd
join client_data ln on ln.client_id = bd.client_id and ln.field_id = 1 and ln.field_value = ...
where bd.field_id = 4
and bd.field_value = ...;
При возрастании объема данных поиск может быть ооочень долгим.
Надеюсь, принцип понятен. Подробней в ссылке ниже.
3️⃣ Другие варианты
Я думаю, можно насобирать еще с десяток вариантов. Зависит от конкретных нужд системы.
Например, хранить часть свойств горизонтально, часть в json в одном поле. Как предложил Филип в этом видео.
⚠️ Каждый из вариантов имеет свои плюсы и минусы. Формат поста не позволяет рассмотреть их все.
——
Вернемся к задаче.
1️⃣ Требования: частое добавление новых свойств, нагруженная OLTP система.
🔸 Горизонтальное - нужно добавить новый столбец в таблицу client_data_h. Что выйдет? Скорее всего, ничего, т.к. система под нагрузкой - таблица заблокирована на изменение структуры.
🔸 Вертикальное - все сведется к вставке новой строки в client_data_field. После этого уже можно хранить свойство в client_data_v.
2️⃣ Требования: поиск по id клиента и бизнесовым свойствам.
С поиском по id клиента - проблем нет в любом варианте. По нему мы без проблем можем достать технические и бизнесовые свойства вне зависимости от объема данных.
🔸 Горизонтальное - PK по id клиента
🔸 Вертикальное - PK по комбинации id клиента + fld_id.
А вот с поиском клиентов по бизнесовым свойствам - проблема. Поиск в действительно большом объеме данных + по любому бизнес полю - это не задача OLTP.
Если оператору хочется производить поиск в данных, придется придумывать некие workaround-решения заточенные под поиск (это может быть, параллельно существующая структура для хранения бизнес полей; совсем другая БД и т.п.).
Если же данных не так что бы и много, то можем попробовать обойтись индексами:
🔸 Горизонтальное - нужно добавить новый индекс на новый столбец. С использованием опции online - это не большая проблема.
🔸 Вертикальное - у нас уже должен быть индекс на комбинацию полей (field_value, field_id). Ничего делать не нужно.
В любом случае, стоит дополнительно обговорить с бизнесом, точно ли им нужен поиск, по всем ли полям и т.п.
Выводы: для нашей задачи больше подходит вертикальное хранение свойств.
Понравилась задача? Палец вверх 👍
Тема холиварная - можно обсудить в нашем ламповом чатике 😉
P.S. В определениях таблиц опущены всевозможные ограничения, FK, PK и т.п.
#решениезадачи #проектирование
Oracle Developer