Роман Теличко

Заметки веб-разработчика/админа

PostgreSQL: Создание индекса для uuid[]

// | 167 просмотров | комментариев (0)

Для начала что такое uuid:

UUID (universally unique identifier) — это стандарт идентификации, используемый в создании программного обеспечения, стандартизированный Open Software Foundation (OSF) как часть DCE — среды распределённых вычислений (Distributed Computing Environment (англ.)). Основное назначение UUID — это позволить распределённым системам уникально идентифицировать информацию без центра координации. Таким образом, любой может создать UUID и использовать его для идентификации чего-либо с приемлемым уровнем уверенности, что данный идентификатор непреднамеренно никогда не будет использован для чего-то ещё. UUID представляет собой 16-байтный (128-битный) номер.

В PostgreSQL, по умолчанию, нет индекса для столбцов массива uuid (uuid[]).
Для примера, вот простая таблица с столбцом массива uuid:

CREATE TABLE someitems (
    items uuid[]
);

Но когда мы пытаемся создать на нем индекс:

CREATE INDEX someitems_items_index ON someitems USING GIN (items);

Получаем следующую ошибку:

ERROR:  data type uuid[] has no default operator class for access method "gin"

Поэтому мы должны создать тип индекса, который понимает, как сравнивать элементы массива uuid (uuid[]).

Выполнять подобные операции нам необходимо под суперпользователем базы данных PostgreSQL — postgres:

su postgres
psql -d yourdatabase
CREATE OPERATOR CLASS _uuid_ops DEFAULT FOR TYPE _uuid USING gin AS
    OPERATOR 1 &&(anyarray, anyarray),
    OPERATOR 2 @>(anyarray, anyarray),
    OPERATOR 3 <@(anyarray, anyarray),
    OPERATOR 4 =(anyarray, anyarray),
    FUNCTION 1 uuid_cmp(uuid, uuid),
    FUNCTION 2 ginarrayextract(anyarray, internal, internal),
    FUNCTION 3 ginqueryarrayextract(anyarray, internal, smallint, internal, internal, internal, internal),
    FUNCTION 4 ginarrayconsistent(internal, smallint, anyarray, integer, internal, internal, internal, internal),
    STORAGE uuid;

Теперь мы можем создать наш индекс и все SELECTы для элементов массива uuid (uuid[]) будут его использовать.
Например, найти все строки, которые содержат конкретный UUID:

SELECT * FROM someitems WHERE items @> ARRAY['171e9457-5242-406d-ab5e-523419794d18']::uuid[];

Это всё. Удачи!