dkLab PostgreSQL patch это небольшой набор патчей для PostgreSQL 8.3, а именно, для расширений ("контрибов") intarray и intagg. Он добавляет 3 написанные на C (а потому быстрые) функции для работы с очень большими наборами предварительно отсортированных массивов.
Чтобы наложить эти патчи, запустите приведенные ниже команды, а затем пересоберите PostgreSQL из исходных кодов, как обычно:
intagg.int_array_append_aggregate(int[]): слияние нескольких массивов в один большой
Специальная агрегатная функция int_array_append_aggregate() позволяет сливать воедино очень большой набор длинных массивов за один агрегатный запрос. Слияние происходит очень быстро, т.к. функция использует несколько оптимизаций при выделении и копировании областей памяти.
Листинг 2: int_array_append_aggregate - пример использования
CREATE TABLE doc(doc_id INTEGER, doc_word_ids INTEGER[]);
INSERT INTO doc(doc_id, doc_word_ids) VALUES(1, '{123, 456, 789, 111}');
...
SELECT int_array_append_aggregate(doc_word_ids) FROM doc;
/* Возвращает ID всех слов, встречающихся во всех документах. */
Даже если таблица doc содержит 10000 строк, каждая из которых имеет по 1000 ID слов в поле doc_word_ids, выполнение запроса займет всего несколько миллисекунд.
Имеется стандартная функция int_array_aggregate, которая использует похожие методы оптимизации и возвращает массив чисел, содержащий в точности те числа, которые были ей переданы на вход. Однако эта функция сливает набор целых чисел, а не набор массивов в один большой массив.
intarray._int_group_count_sort(int[], bool): сортировка по частоте
Представьте, что у вас есть очень большой отсортированный массив целых чисел, значения в котором могут повторяться. Вам нужно определить, какие из значений в массиве встречаются наиболее часто, а какие наименее. Функция _int_group_count_sort() поможет вам это сделать, затратив минимум ресурсов процессора даже при работе с очень большим массивом. В некоторых случаях функция дает более чем тысячекратный прирост производительности по сравнению со стандартным использованием запроса вида "GROUP BY ... ORDER BY COUNT(*)".
Как видите, функция возвращает двумерный массив. Первый элемент каждого подмассива равен частоте вхождения величины в исходный массив, а второй самой этой величине. Результат отсортирован по убыванию (sort_asc = false) или возрастанию (sort_asc = true) частоты вхождения величин.
Обратите внимание на то, что входной массив ОБЯЗАТЕЛЬНО должен быть отсортирован (используйте функцию intarray.sort()), иначе _int_group_count_sort() будет возвращать неверный результат.
Имя _int_group_count_sort выглядит, возможно, странновато, однако таков уж принятый стандарт именования функций в модуле intarray...
intarray.bidx(int[], int): поиск методом деления пополам в отсортированном массиве
Данная функция реализует алгоритм поиска "методом деления пополам" в отсортированном массиве. Она возвращает позицию элемента value в отсортированном массиве list_sorted или 0, если элемент найти не удалось. Алгоритм поиска очень быстр и может обрабатывать тысячи массивов за единицы миллисекунд. Функция может быть использована, если вы хотите быстро отфильтровать значения в большом наболе целых чисел внутри хранимой процедуры или SQL-запроса. Вот иллюстрация использования функции:
list := ARRAY(SELECT * FROM generate_series(2,1000000,1));
SELECT bidx(list, 765432); /* возвращает 765431, позицию числа 765432 */
SELECT bidx(list, -100); /* возвращает 0, элемент не найден */
Обратите внимание на то, что входной массив ОБЯЗАТЕЛЬНО должен быть отсортирован (используйте функцию intarray.sort()), иначе bidx() будет возвращать неверный результат.
Резюме
Функции в составе dkLab PostgreSQL patch могут быть полезны при разработке высоконагруженных проектов, которым не хватает чисто реляционных возможностей SQL, а работа происходит с большими массивами целых чисел (например, ID объектов).