Представление PostgreSQL для объекта поля JSONB _array_ (с индексацией) - PullRequest
0 голосов
/ 11 декабря 2019

Вопрос

Как создать PostgreSQL View на основе объекта поля JSONB массив , с соответствующими индексами ? Пример ниже.

  1. Концептуально, как следует применять индексирование при использовании с представлениями и массивом JSONB?
  2. Каков правильный синтаксис для создания соответствующих индексов?
  3. Дан ли пример представления правильному / оптимальному способу построения представления для этого варианта использования?

Пример

Таблица

CREATE TABLE "ProductLists"
(
    id uuid NOT NULL DEFAULT gen_random_uuid(),
    listName text NOT NULL
    productIds jsonb NOT NULL DEFAULT '[{ productId:0 }]'::jsonb,
)

Представление (можно изменить)

При следующем представлении:

SELECT "ProductLists".id AS listId,
    jsonb_array_elements("ProductLists".productIds) ->> 'productId'::text AS productId
   FROM "ProductLists";

Factors

  • Корень JSONB - это массив, а не объект (а это не так в большинстве примеров индексирования)
  • Потенциально будут миллионы элементов ProductList
  • Количество productIds в каждом списке, как правило, будет меньше 100
  • Таблица будет иметь как высокие чтения, так и записи
  • Пример SQL представления может или не может быть оптимальным для этой целии может быть изменено

Спасибо за любой ввод!

1 Ответ

1 голос
/ 11 декабря 2019

Индекс GIN для столбца jsonb будет поддерживать несколько операторов JSON . Одним из них является оператор @>, который также работает с массивами JSON.

Следующий индекс:

create index on product_list using gin (product_ids);

Запрос, который может потенциально использовать вышеуказанный индекс, будет выглядеть следующим образом:

select *
from product_list
where product_ids @> '[{"productId": 42}]'::jsonb;

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

Единственный способ использовать индекс в представлении - включить в него столбец JSON:

create view normalized_list
as
SELECT pl.id AS list_id,
       t.product_id, 
       pl.product_ids
FROM product_list pl
   CROSS JOIN jsonb_array_elements(pl.product_ids) ->> 'id' AS t(product_id)
;

Запрос, подобный следующему:

select id, product_Id
from normalized_list
where product_ids @> '[{"id":42}]'::jsonb;

будет использовать индекс GIN.


Обратите внимание, что если вы только хотите хранить идентификаторы денормализованным образом, собственный целочисленный массив (product_ids int[]) будет более эффективным и сделает таблицу существенно меньше

...