Заранее извиняюсь ... длинный вопрос.
Предположим, у меня есть таблица table_x
с 20 полями в ней:
table_x_id (identity pk)
int1
int...
int8
text1
text...
text8
jsonb1
jsonb2
Теперь предположим, что я хочу поддерживать быстрыйдоступ к сгруппированным данным (скажем, к полям int1, int2, text1_id, text2_id и jsonb1) в table_x
. Назовите это Report 1
. На самом деле данные не играют важной роли в постановке этого вопроса, но вот воображаемый фрагмент из Report 1
:
+-----------------------------------------------------------------------+
| int1value int2value text1value text2value jsonb1->item1 jsonb1->item2 |
+-----------------------------------------------------------------------+
| (table_x_id) 12 |
| (table_x_id) 20 |
| (table_x_id) 34 |
+-----------------------------------------------------------------------+
Теперь представьте, что у меня есть три или более таких потребности в отчетности, и что каждый отчет включает в себя группировкумногие (но не все) поля в table_x
.
Каждое текстовое поле может легко достигать, скажем, до 1000 символов, а поля jsonb, хотя и не большие, просто усугубляют проблему.
Задача: ускорить группировку для создания отчетов.
Чтобы ускорить группирование и уменьшить размер строки table_x, я разбил уникальные значения текстового поля (которые действительно имеют много совпадений) в отдельном text_table
.
Теперь table_x
это:
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1
jsonb2
Что касается группировки, то я тогда думал сохранить хешсоответствующих столбцов внутри самого table_x
, используя вызовы digest () в триггере вставки / обновления. (Идея заключалась в том, чтобы преобразовать все соответствующие поля в моей группировке в строки, объединить их вместе и запустить хеш для результирующей строки.)
Теперь table_x
is:
table_x_id (identity pk)
int1
int...
int8
text1_id (lookup)
text..._id (lookup)
text8_id (lookup)
jsonb1
jsonb2
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1)
hash2_bytea (based on int3, int7, text3_id, jsonb1 and jsonb2)
hash3_bytea (based on int2, int5, text1_id and jsonb2)
Теперь отчет требует больше поисков, но это быстро, и теперь мне нужно сгруппировать только по hash1_bytea, чтобы добиться того же результата Report 1
.
Страх: эквивалентные поля jsonb в разныхстроки могут быть не эквивалентны при сравнении их представлениями jsonb :: text. Из того, что я прочитал здесь , эти опасения кажутся оправданными.
Но если я не могу преобразовать значения jsonb в текст детерминистическим способом, мое "поле хеш-функции внутри таблицы"решение разваливается по швам.
Затем я решил сохранить значения jsonb в отдельном jsonb_table
, где я гарантирую, что у каждой строки есть уникальный объект jsonb.
jsonb_table
:
jsonb_id (identity pk)
jsonb (unique jsonb)
Для любого уникального объекта jsonb (не принимая во внимание упорядочение объектов в нем, когда оно представлено в тексте) теперь есть одна и ровно одна строка в jsonb_table
, которая представляет его.
Теперьtable_x
- это:
table_x_id (identity pk)
int1
int...
int8
text1_id (fk lookup)
text..._id (fk lookup)
text8_id (fk lookup)
jsonb1_id (fk lookup)
jsonb2_id (fk lookup)
hash1_bytea (based on int1, int2, text1_id, text2_id and jsonb1_id )
hash2_bytea (based on int3, int7, text3_id, jsonb1_id and jsonb2_id )
hash3_bytea (based on int2, int5, text1_id and jsonb2_id )
Да, поддержание text_table
и jsonb_table
- это хлопотно, но это выполнимо, и table_x
теперь кажется достаточно эффективным, быстро способным поддерживать несколько хешей.
Кажется, я выполнил быструю и точную группировку по нескольким видам группировок с несколькими полями.
У меня есть два вопроса на этот момент:
Является ли мой подход разумным и относительно благополучным? подписаны? Или есть лучший способ для достижения моих целей?
JSON в jsonb1 и jsonb2 - это на самом деле массив редко используемых, специальных пар ключ-значение, однако данныев jsonb1 и jsonb2 нужна ссылочная целостность с данными, хранящимися в нормализованных реляционных таблицах. В таком случае было бы плохой идеей создать jsonb_child_table
?
jsonb_child_table
:
jsonb_child_id (pk identity)
jsonb_id (fk to jsonb_table)
key_lookup_id (fk lookup)
value_lookup_id (fk lookup)
Опять хлопот, чтобы сделатьуверен, что записи в jsonb_child_table
являются правильными пробоями поля jsonb в jsonb_table
, но, делая это таким образом, я могу:
- быстро поддерживать всю эту информацию о группировке, обсужденную до
- гарантировать хорошую ссылочную целостность
- отчет по jsonb1 (например) с использованием полей в
jsonb_child_table
, упорядоченных (например) по метаданным (через соединение SQL с использованием key_lookup_id
), не хранящихся в самом jsonb1.
Эта последняя точка пули, кажется, повторяет то, что я читал в других местах SO ... что поддержание массива значений ключей в jsonb требует переосмысления ... Если вы хотите обеспечить упорядочение пар, имейте ссылочную целостностьи получать данные быстрее, JSONB может быть плохим выбором. Однако в случае my ведение таблицы заголовков jsonb (с одним полем идентификатора внешнего ключа) позволяет быстро группировать разнородные коллекции (в table_x
) пар значений. Поэтому я вижу преимущества в поддержании одинаковых данных как в jsonb (для легкой группировки), так и в реальных таблицах (для RI и более быстрых, более чистых отчетов).
Да, этот 2-й вопрос достоин другого SOвопрос сам по себе, но кажется, что вся куча взаимосвязана, поэтому я представляю все это здесь в одном (простите) длинном сообщении.
Заранее спасибо за отзыв!