Практические ограничения индексов выражений в PostgreSQL

#sql #database-design #postgresql #expression #indexing

#sql #база данных-дизайн #postgresql #выражение #индексирование

Вопрос:

У меня есть необходимость хранить данные, используя тип HSTORE и индексировать по ключу.

 CREATE INDEX ix_product_size ON product(((data->'Size')::INT))
CREATE INDEX ix_product_color ON product(((data->'Color')))
etc.
  

Каковы практические ограничения использования индексов выражений? В моем случае может быть несколько сотен различных типов данных, следовательно, несколько сотен индексов выражений. Каждый запрос insert, update и select должен обрабатываться с учетом этих индексов, чтобы выбрать правильный.

Комментарии:

1. Я использую последнюю версию PG.

Ответ №1:

Я никогда не играл с hstore, но я делаю нечто подобное, когда мне нужен столбец EAV, например:

 create index on product_eav (eav_value) where (eav_type = 'int');
  

Ограничение при этом заключается в том, что вам нужно быть явным в вашем запросе, чтобы использовать его, т. Е. этот запрос не будет использовать вышеупомянутый индекс:

 select product_id
from product_eav
where eav_name = 'size'
and eav_value = :size;
  

Но этот был бы:

 select product_id
from product_eav
where eav_name = 'size'
and eav_value = :size
and type = 'int';
  

В вашем примере это, вероятно, должно быть больше похоже:

 create index on product ((data->'size')::int) where (data->'size' is not null);
  

Это должно избежать добавления ссылки на индекс, когда нет записи размера. В зависимости от используемой вами версии PG запрос может потребоваться изменить следующим образом:

 select product_id
from products
where data->'size' is not null
and data->'size' = :size;
  

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

 create unique index foo_bar_key on foo (bar) where (cond);
  

Следующее не будет:

 alter table foo add constraint foo_bar_key unique (bar) where (cond);
  

Но это приведет:

 alter table foo add constraint foo_bar_excl exclude (bar with =) where (cond);
  

Комментарии:

1. Спасибо. Я не понимаю, почему вы говорите, что «(data-> ‘size’ не равен нулю)» необходимо. С сайта PostgreSQL : : Частичный индекс — это индекс, построенный над подмножеством таблицы; подмножество определяется условным выражением (называемым предикатом частичного индекса). Индекс содержит записи только для тех строк таблицы, которые удовлетворяют предикату.» Поэтому, конечно, если я не добавлю конкретный ключ HSTORE, записи индекса не будет.

2. Внутри индекса, без предложения where, индекс добавлял бы запись для каждого независимо от того, определен размер или нет. Частичный индекс (с предложением where) исправляет это тем, что добавляет запись только для строк, удовлетворяющих условию. Это делает индекс намного меньше, поскольку он содержит записи только для соответствующих строк.

3. Ах, вы просто гарантируете, что он не добавляет запись индекса для случаев, когда данные определены с нулевым значением для ключа. Хорошо, я не думал, что это произойдет, но я понял вашу точку зрения.

4. Хе-хе, это случается, и это один из многих случаев, когда частичные индексы полезны. 🙂

5. Исправление: я имею в виду индекс выражения.