intarray — работа с массивами целых чисел#

Примечание

Эта страница переведена при помощи нейросети GigaChat.

Модуль intarray предоставляет ряд полезных функций и операторов для работы с массивами целых чисел без нулевых значений. Также поддерживается выполнение индексированных поисков с использованием некоторых из этих операторов.

Все эти операции вызовут ошибку, если предоставленный массив содержит какие-либо элементы NULL.

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

Этот модуль считается «доверенным», то есть его могут устанавливать неподключенные пользователи, которые имеют привилегию CREATE на текущей базе данных.

Функции и операторы intarray#

Функции, предоставляемые модулем, показаны в таблице «Функции intarray», а операторы - в таблице «Операторы intarray».

Функции intarray:

Функция

Описание

Пример(ы)

icount ( integer[] ) → integer

Возвращает количество элементов в массиве

icount('{1,2,3}'::integer[])3

sort ( integer[],dir - text ) → integer[]

Сортирует массив в порядке возрастания или убывания. dir должно быть равно asc или desc

sort('{1,3,2}'::integer[], 'desc'){3,2,1}

sort ( integer[] ) → integer[] | sort_asc ( integer[] ) → integer[]

Сортировка по возрастанию

sort(array[11,77,44]){11,44,77}

sort_desc ( integer[] ) → integer[]

Сортировка по убыванию

sort_desc(array[11,77,44]){77,44,11}

uniq ( integer[] ) → integer[]

Удаляет соседние дубликаты. Часто используется с sort для удаления всех дубликатов

uniq('{1,2,2,3,1,1}'::integer[]){1,2,3,1} | uniq(sort('{1,2,3,2,1}'::integer[])){1,2,3}

idx ( integer[], item - integer ) → integer

Возвращает индекс первого элемента массива, соответствующего item, или 0, если нет совпадения

idx(array[11,22,33,22,11], 22)2

subarray ( integer[], start - integer, len - integer ) → integer[]

Извлекает часть массива, начиная с позиции start, с элементами len

subarray('{1,2,3,2,1}'::integer[], 2, 3){2,3,2}

subarray ( integer[],start - integer ) → integer[]

Извлекает часть массива, начиная с позиции start

subarray('{1,2,3,2,1}'::integer[], 2){2,3,2,1}

intset ( integer ) → integer[]

Создает массив с одним элементом

intset(42){42}

Операторы intarray:

Оператор

Описание

integer[] && integer[]boolean

Пересекаются ли массивы (имеют хотя бы один общий элемент)?

integer[] @> integer[]boolean

Содержит ли левый массив правый массив?

integer[] <@ integer[]boolean

Вложен ли левый массив в правый массив?

# integer[]integer

Возвращает количество элементов в массиве

integer[] # integerinteger

Возвращает индекс первого элемента массива, соответствующего правому аргументу, или 0, если совпадений нет. (То же самое, что и функция idx.)

integer[] + integerinteger[]

Добавляет элемент в конец массива

integer[] + integer[]integer[]

Конкатенирует массивы

integer[] - integerinteger[]

Удаляет записи, соответствующие правому аргументу из массива

integer[] - integer[]integer[]

Удаляет элементы правого массива из левого массива

integer[] | integerinteger[]

Вычисляет объединение аргументов

integer[] | integer[]integer[]

Вычисляет объединение аргументов

integer[] & integer[]integer[]

Вычисляет пересечение аргументов

integer[] @@ query_intboolean

Удовлетворяет ли массив запросу? (см. ниже)

query_int ~~ integer[]boolean

Удовлетворяет ли массив запросу? (коммутатор @@)

Операторы &&, @> и <@ эквивалентны встроенным операторам PostgreSQL с теми же именами, за исключением того, что они работают только с целочисленными массивами, которые не содержат нулей, тогда как встроенные операторы работают для любого типа массива. Это ограничение делает их быстрее, чем встроенные операторы во многих случаях.

Операторы @@ и ~~ проверяют, удовлетворяет ли массив запросу , который выражается значением специализированного типа данных query_int. Запрос состоит из целочисленных значений, которые проверяются на соответствие элементам массива, возможно, объединенных с использованием операторов & (И), | (ИЛИ) и ! (НЕ). Скобки могут использоваться при необходимости. Например, запрос 1&(2|3) соответствует массивам, содержащим 1 и также содержащим либо 2, либо 3.

Поддержка индексов#

intarray поддерживает индексы для операторов &&, @>, и @@, а также обычное равенство массивов.

Предоставляются два параметризированных класса операторов GiST-индекса: gist__int_ops (используется по умолчанию) подходит для небольших и средних наборов данных, тогда как gist__intbig_ops использует большую подпись и более подходит для индексирования больших наборов данных (т.е. столбцов, содержащих большое количество различных значений массива). Реализация использует структуру данных RD-дерева со встроенным сжатием с потерями.

gist__int_ops аппроксимирует множество целых чисел как массив целых диапазонов. Его необязательный целочисленный параметр numranges определяет максимальное количество диапазонов в одном индексе ключа. Значение по умолчанию для numranges равно 100. Допустимые значения находятся между 1 и 253. Использование больших массивов в качестве ключей индекса GiST приводит к более точному поиску (сканированию меньшей доли индекса и меньшего количества страниц кучи) за счет увеличения размера индекса.

gist__intbig_ops аппроксимирует множество целых чисел в виде сигнатуры битовой карты. Его необязательный целочисленный параметр siglen определяет длину подписи в байтах. Длина подписи по умолчанию составляет 16 байт. Допустимая длина подписи варьируется от 1 до 2024 байт. Более длинные подписи приводят к более точному поиску (сканируя меньшую долю индекса и меньше страниц кучи), но увеличивают размер индекса.

Существует также нестандартный класс операторов GIN gin__int_ops, который поддерживает эти операторы, а также <@.

Выбор между индексированием GiST и GIN зависит от относительных характеристик производительности GiST и GIN, которые обсуждаются в другом месте.

Пример#

-- a message can be in one or more “sections”
CREATE TABLE message (mid INT PRIMARY KEY, sections INT[], ...);

-- create specialized index with signature length of 32 bytes
CREATE INDEX message_rdtree_idx ON message USING GIST (sections gist__intbig_ops (siglen = 32));

-- select messages in section 1 OR 2 - OVERLAP operator
SELECT message.mid FROM message WHERE message.sections && '{1,2}';

-- select messages in sections 1 AND 2 - CONTAINS operator
SELECT message.mid FROM message WHERE message.sections @> '{1,2}';

-- the same, using QUERY operator
SELECT message.mid FROM message WHERE message.sections @@ '1&2'::query_int;

Тестирование производительности#

Каталог contrib/intarray/bench содержит набор тестов для тестирования производительности, которые можно запустить на установленном сервере PostgreSQL (для этого нужно установить пакет DBD::Pg). Чтобы запустить тесты:

cd .../contrib/intarray/bench
createdb TEST
psql -c "CREATE EXTENSION intarray" TEST
./create_test.pl | psql TEST
./bench.pl

Сценарий bench.pl имеет множество опций, которые отображаются при его запуске без аргументов.