@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