Рассмотрим следующую таблицу, в которой записаны изменения цен на разные товары, принадлежащие разным компаниям разных категорий.
Column | Type | Modifiers
-----------------+--------+-----------
category_id | bigint | not null
product_id | bigint | not null
industry_id | bigint | not null
time | bigint | not null
price | bigint | not null
product_info | json | not null
Indexes:
"price_change_pk" PRIMARY KEY, btree (category_id, product_id, price, "time")
Foreign-key constraints:
"orders_industry_id" FOREIGN KEY (industry_id) REFERENCES industry_info(industry_id)
"orders_product_id" FOREIGN KEY (product_id) REFERENCES device_info(product_id)
"orders_category_id" FOREIGN KEY (categoy_id) REFERENCES category_info(category_id)
Для ясности значения столбца будут:
category_id
- отдельная таблица будет иметь идентификатор (уникальное значение bigint), сопоставленный с именем категории - 100 категорий
(электроника, мода, здоровье, спорт, игрушки, книги)
industry_id
- отдельная таблица будет иметь идентификатор (уникальное значение bigint), сопоставленный с именем отрасли - несколько тысяч отраслей в категории
(Nokia, Apple, Microsoft, PeterEngland, Rubik, Nivia, Cosco)
product_id
- отдельная таблица будет иметь идентификатор (уникальное значение bigint), сопоставленный с именем продукта - миллионы продуктов в отрасли
time
(время unix как bigint) - время, в котороецена была изменена,
price
- несколько тысяч различных значений - (200, 10000, 14999, 30599, 450)
product_info
- JSON, который содержит дополнительные деталипродукт(количество пар ключ / значение может варьироваться)
{seller:"ABC Assured", discount:10, model:XYZ, EMIoption:true, EMIvalue:12, festival_offer:28, market_stat:comingsoon}
Таблица запрашивается несколькими способами для анализа тенденции изменения цены продукта в виде графика в виде дня / недели / месяца в виде часа/ день / неделя / месяцТенденция может быть основана на нет.продуктов, при этом изменяются уникальные продукты.
Например, Google Sample Trend
Хранение JSON в том виде, в каком оно есть (как string
), использует больше памяти.Поэтому я попытался сохранить ключ-значение в json с увеличивающимся серийным идентификатором в отдельной таблице, и эти идентификаторы используются.
Как
Keys (citext, bigint)
seller - 1
discount - 2
model - 3
EMIoption - 4
EMIvalue - 5
festival_offer - 6
...
...
currency - 25
Values (citext, bigint)
ABC Assured - 1
10 - 2
XYZ - 3
true - 4
12 - 5
28 - 6
comingsoon - 7
...
...
ZYX - 106
rupees - 107
american dollars - 108
canadian dollars - 109
Prime seller - 110
{seller:"ABC Assured", discount:10, model:XYZ, EMIoption:true, EMIvalue:12, festival_offer:28, market_stat:comingsoon, curreny: rupees}
становится
{"1":1, "2":2", "3":3, "4":4, "5":5, "6":6, "7":7, "25":107}
{seller:"Prime seller", discount:10, model:XYZ, EMIoption:true, EMIvalue:12, festival_offer:28, market_stat:comingsoon, curreny: "canadian dollars"}
становится
{"1":110, "2":2", "3":3, "4":4, "5":5, "6":6, "7":7, "25":109}
Дляоколо 20 МБ данных, он уменьшен примерно на 1,5 ГБ.
Увеличение количества ключей в ключе, увеличение серийных номеров.Поэтому я попытался сохранить десятичное число в шестнадцатеричном формате.
{"1":1, "2":2", "3":3, "4":4, "5":5, "6":6, "7":7, "25":107}
становится
{"1":1, "2":2", "3":3, "4":4, "5":5, "6":6, "7":7, "19":"6B"}
{"1":110, "2":2", "3":106, "4":4, "5":5, "6":6, "7":7, "25":109}
становится
{"1":, "2":2", "3":"6A", "4":4, "5":5, "6":6, "7":7, "19":"6D"}
Так что же значит хранить эти десятичные целые числа в виде шестнадцатеричных целых.
- Сохранить место для хранения?(потому что визуально он выглядит сжатым)
- Сохраняет ли JSON тип данных ключ-значение или они хранятся в виде строк?
- Сжатие данных?
- Улучшениепроизводительность чтения?
- или в любом случае ее можно улучшить?(Индексирование или любое другое?)
В обычном приложении psql выполнение запросов занимает несколько минут.Поскольку он соответствует данным временного ряда, мы используем расширение TimescaleDB, а его механизм шардинга ускоряет выполнение запроса, но нам нужны результаты в секундах.
Примеры запросов : чтобы проверить, сколькораз цена была изменена на 500, для всех продуктов в данной категории, в группе месяцев по дням.
select count(*), to_char(date_trunc('day', to_timestamp(time/1000) at time zone 'Asia/Kolkata'), 'YYYY/MM/DD') as unit, price
from price_change
where category_id = 1000000010 and time between 1514745000000 and 1517423400000
and price = 500
group by price, unit;
Чтобы проверить, сколько раз цена была изменена на любой из (100 200 300 400 800 500 600 700 800 800 900 000),для всех продуктов в данной категории в группе за последние 10 месяцев по каждому месяцу.
select count(*), to_char(date_trunc('month', to_timestamp(time/1000) at time zone 'Asia/Kolkata'), 'YYYY/MM/DD') as unit, price
from price_change
where category_id = 1000000010 and time between 1514745000000 and 1517423400000
and price in (100,200,300,400,500,600,700,800,900,1000) group by price, unit;
Чтобы выбрать сведения о продукте, цена которого была изменена в данном временном диапазоне, в данной категории
select product_id, product_name, price, to_char(date_trunc('day', to_timestamp(time/1000) at time zone 'Asia/Kolkata'), 'YYYY/MM/DD') as timestamp
from price_change
join products using product_id
where price_change.category_id = 1000000010
and price_change.time between 1514745000000 and 1517423400000;
Чтобы выбрать данные об отрасли и идентификаторе продукта, цена которого была изменена в заданном временном диапазоне, в данной категории
select industry_id, product_id, price
from price_change
join industries using industry_id
where price_change.category_id = 1000000010
and price_change.time between 1514745000000 and 1517423400000;
Чтобы выбрать подробности об изменении цены продукта, во временном диапазонесо скидкой 10%, в определенной категории
select product_id, product_name, price, to_char(date_trunc('day', to_timestamp(time/1000) at time zone 'Asia/Kolkata'), 'YYYY/MM/DD') as timestamp
from price_change
join products using product_id
where price_change.category_id = 1000000010
and price_change.time between 1514745000000 and 1517423400000
and product_info->>'discount'=10;
Чтобы выбрать подробности изменения цены товара, во временном диапазоне, проданном конкретным продавцомв определенной категории
select product_id, product_name, price, to_char(date_trunc('day', to_timestamp(time/1000) at time zone 'Asia/Kolkata'), 'YYYY/MM/DD') as timestamp
from price_change
join products using product_id
where price_change.category_id = 1000000010
and price_change.time between 1514745000000 and 1517423400000
and product_info->>'seller'='ABC Assured';
В большинстве случаев запрос не будет содержать category_id
в столбцах выбора.