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[] # integer → integer | Возвращает индекс первого элемента массива, соответствующего правому аргументу, или 0, если совпадений нет. (То же самое, что и функция idx.) |
integer[] + integer → integer[] | Добавляет элемент в конец массива |
integer[] + integer[] → integer[] | Конкатенирует массивы |
integer[] - integer → integer[] | Удаляет записи, соответствующие правому аргументу из массива |
integer[] - integer[] → integer[] | Удаляет элементы правого массива из левого массива |
integer[] | integer → integer[] | Вычисляет объединение аргументов |
integer[] | integer[] → integer[] | Вычисляет объединение аргументов |
integer[] & integer[] → integer[] | Вычисляет пересечение аргументов |
integer[] @@ query_int → boolean | Удовлетворяет ли массив запросу? (см. ниже) |
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 имеет множество опций, которые отображаются при его запуске без аргументов.