@Tregoreg поднял вопрос в комментарии к предложенной им награде:
Я не нашел, что текущие ответы работают. Использование индекса GIN для столбца с типом массива не увеличивает производительность оператора ANY (). Неужели решения нет?
В принятом ответе @Frank предлагается использовать операторы массива , что по- прежнему верно для Postgres 11. Руководство:
... стандартный дистрибутив PostgreSQL включает класс операторов GIN для массивов, который поддерживает индексированные запросы с использованием следующих операторов:
<@
@>
=
&&
Полный список классов встроенных операторов для индексов GIN в стандартной поставке находится здесь.
В Postgres индексы привязаны к операторам (которые реализованы для определенных типов), а не только к типам данных, функциям или чему-либо еще. Это наследие оригинального дизайна Postgres в Беркли, и сейчас его очень сложно изменить. И в целом работает нормально. Вот ветка pgsql-bugs, где Том Лейн комментирует это.
Некоторые функции PostGis (например, ST_DWithin()) нарушают этот принцип, но это не так. Эти функции внутренне переписаны для использования соответствующих операторов .
Проиндексированное выражение должно находиться слева от оператора. Для большинства операторов ( включая все вышеперечисленные ) планировщик запросов может добиться этого, переворачивая операнды, если вы поместите индексированное выражение вправо - при условии, что COMMUTATORбыл определен a . ANYКонструкция может быть использована в комбинации с различными операторами и не является сам оператор. При использовании constant = ANY (array_expression)только индексы, поддерживающие =оператор для элементов массива, будут квалифицированы, и нам понадобится коммутатор для = ANY(). Индексы GIN отсутствуют.
Postgres в настоящее время недостаточно умен, чтобы получить из него выражение, индексируемое GIN. Во - первых, constant = ANY (array_expression)это не полностью эквивалентны с array_expression @> ARRAY[constant]. Операторы массива возвращают ошибку, если задействованы какие-либо элементы NULL , в то время как ANYконструкция может обрабатывать NULL с любой стороны. И есть разные результаты для несоответствия типов данных.
Связанные ответы:
В сторону
При работе с integerмассивами ( int4, не int2или int8) без NULLзначений (как предполагает ваш пример) рассмотрите дополнительный модуль intarray, который предоставляет специализированные, более быстрые операторы и поддержку индексов. Увидеть:
Что касается UNIQUEограничения в вашем вопросе, который остался без ответа: это реализовано с помощью индекса btree для всего значения массива (как вы и подозревали) и вообще не помогает с поиском элементов . Детали:
jsonbи индексы? postgresql.org/docs/9.5/static/functions-json.html и postgresql.org/docs/9.5/static/datatype-json.html#JSON-INDEXING