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

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

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

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

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

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

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

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

Список функций, предоставляемых модулем intarray, приведен в таблице Таблица F.9, операторы - в таблице Таблица F.10.

Таблица F.9. 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

Возвращает индекс первого элемента массива, соответствующего элементу, или 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}


Таблица F.10. 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

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


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

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

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

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, которые обсуждаются в другом месте.

F.21.3. Пример #

-- 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;

F.21.4. Бенчмарк #

Каталог исходного кода contrib/intarray/bench содержит набор тестов производительности, который можно запустить на установленном сервере Tantor BE. (Также требуется установка DBD::Pg). Для запуска:

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

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

F.21.5. Авторы #

Всю работу выполнили Федор Сигаев () и Олег Бартунов (). Дополнительную информацию можно найти на странице http://www.sai.msu.su/~megera/postgres/gist/. Андрей Октябрьский внес большой вклад в добавление новых функций и операций.