Pull to refresh

Comments 13

Есть теория, что проектированием БД занимались MongoDB-шники. Узнаю неповторимый стиль. :-) Жуткая денормализация. Это делать опасно. Такое можно мудрить только в крайне редких случаях, когда нужно поднять скорость выполнения запросов и ничего другое уже не помогает.

Не-не, что вы! ))

jsd тут - это CTE, которую собрали сначала из нормальных реляционных записей в базе.

Интересно. Но я вот только не пойму, зачем реляционную CEБД PostgreSQL использовать таким образом - хранить сырые объекты в JSON? Можно ведь использовать объектную NoSQL СУБД - она специально сконструирована под такое использование. Или - с помощью какой-нибудь ОРМ либо вручную отображать объекты на обычные поля обычных таблиц (хотя бы частично, для тех полей, по которым поиск и фильтрация часто производятся)?

Или хранение JSON и манипуляции с ним - это очень маленькая часть большого проекта, которому в остальной части требуется именно реляционная СУБД?

До появления schemaless json(b) в постгрессе интернет-магазин реализовывали в основном так: справочник типов параметров, справочник номенклатурных типов, таблица-схема с объявлением типов параметров, участвующих в определении номенклатурного типа; затем каждая номенклатурная позиция в своей таблице, и плюс в другой таблице заполнялись значения параметров для соответствующего номенклатурного типа. Уже только на этом этапе "достать" из базы описание товара с типом, например, "телевизор" требовало множественных джоинов, причем, в процессе участвовали таблицы-связки с отношениями many-to-many.

С появлением json(b) документ-описание типа номенклатуры стало можно хранить сразу в той же строке, в которой объявляется сам номенклатурный тип:

  • для тетради там будут объявлены параметры "type_of_pages: {"oneOf": ["diagonal", "squares", "horizontal"]}"

  • а для телевизора там может быть "refresh_frequency", "mass", "packed_mass"...

При этом, если добывается позиция из базы, достаточно весьма простого джоина к справочнику номенклатурных типов, который, раз уж уже попал в выборку, уже содержит и все параметры, дополнительных джоинов со сложными отношениями к этому добавлять не надо

И при этом сохраняется возможность прицепить другие, обычно нормализованные данные: пользователь-автор позиции в базе, компания, которой принадлежит номенклатурный тип (чтобы не показывать другим клиентам чужие типы, например).

Если же делать на монге, то:

  • либо придётся выносить и нормализованные данные туда же, по пути получив много веселья с aggregation pipelines и с индексами

  • либо делать запросы в базы в несколько проходов: сначала достать номенклатуру, узнать ее тип, сходить в монгу, достать не нормализуемые данные оттуда, сходить опять в базу за оставшимися данными

При этом JSON-инфраструктура в постгресе сделана весьма грамотно. Один только json_agg, поддерживающий все плюшки агрегатных функций, чего стоит. Можно просто бросить в постгрес готовый JSON, заставить его развернуть его в табличное представление, промэтчить его, обернуть конкретные поля "колясками", NULLIF-ами, окошками (и прочими всеми имеющимися средствами обычного SQL), промаркировать ввод, вставить позиции, соответствующие критерию, выплюнуть обратно другой JSON, в котором каждая входная запись имеет маркировку, например, вставилось ли, если нет, то по какой причине.

зачем реляционную CEБД PostgreSQL использовать таким образом - хранить сырые объекты в JSON?

Возможно, я недостаточно акцентировал внимание на том моменте, что этот кейс не про хранение JSON, а про его использование в качестве промежуточной структуры - либо как словаря с доступом по ключу вместо множественных CTE Scan, либо как параметра-выборки, передаваемого на вход запроса в качестве $1-значения.

 зачем реляционную CEБД PostgreSQL использовать таким образом - хранить сырые объекты в JSON? 

Обычно ответ - ACID, если ACID требования нет, транзакционность не нужна, тогда да хранить и обрабатывать json в pg - дорого и неэффективно.

очень просто.

Для начала посгря быстрее в большинстве ситуаций. Учитывая ACID , триггеры , процедуры и прочие плюшки, вопрос скорее в чем смысл использовать MongoDB.

Во вторых jsonb поле можно использовать только там, где и нужно хранить денормализованные данные. А не плодить 30 таблиц. Например, raw json запроса. Metadata NFT токенов. Настройки. Да бесчисленное множество таких ситуаций.

Кажется главная проблема исходного запроса в том, что вообще не ясно что происходит (вообще сложно понять какая это часть запроса, возможно имея весь запрос было бы более понятно)

И боюсь показаться некомпетентным, но зачем ключевое слово TABLE?

(TABLE jsd)

И боюсь показаться некомпетентным, но зачем ключевое слово TABLE?

Это "синтаксический сахар", который позволяет писать короче обращение к CTE (или таблицам) вида 1 строка/1 столбец - в отдельной статье чуть больше информации.

возможно имея весь запрос было бы более понятно

Вряд ли. Алгоритмически - там по определенным правилам из нескольких таблиц собирается "большая" CTE, из которой потом по относительно небольшому набору ключей надо "выдернуть" некоторые записи.

Классический JOIN пары CTE дает Nested Loop с множественными проходами по "большой" CTE, из которой N-1 запись каждый раз бессмысленно отфильтровывается - об этом как раз и написано в статье про "ословаривание".

Да, действительно удобная штука и в целом статья крайне полезная. Вроде-бы не могу найти в документации PostgreSQL или не там ищу

Благодарю, я, видимо, слеп

Sign up to leave a comment.