Перейти к основному содержимому

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 или descsort('{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, с элементами lensubarray('{1,2,3,2,1}'::integer[], 2, 3){2,3,2}
subarray ( integer[],start - integer ) → integer[]Извлекает часть массива, начиная с позиции startsubarray('{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 имеет множество опций, которые отображаются при его запуске без аргументов.