11.10. Семейства и классы операторов #
В определении индекса можно указать класс операторов для каждого столбца индекса.
CREATE INDEXимя
ONтаблица
(столбец
класс_оп
[ (параметры_класса_оп
) ] [параметры сортировки
] [, ...]);
Класс операторов определяет, какие операторы будет использовать индекс для этого столбца. Например, индекс-B-дерево по столбцу int4
будет использовать класс int4_ops
; этот класс операторов включает операции со значениями типа int4
. На практике часто достаточно принять класс операторов, назначенный для типа столбца классом по умолчанию. Однако для некоторых типов данных могут иметь смысл несколько разных вариантов индексирования и реализовать их как раз позволяют разные классы операторов. Например, комплексные числа можно сортировать как по вещественной части, так и по модулю. Получить два варианта индексов для них можно, определив два класса операторов для данного типа и выбрав соответствующий класс при создании индекса. Выбранный класс операторов задаст основной порядок сортировки данных (его можно уточнить, добавив параметры COLLATE
, ASC
/DESC
и/или NULLS FIRST
/NULLS LAST
).
Помимо классов операторов по умолчанию есть ещё несколько встроенных:
Классы операторов
text_pattern_ops
,varchar_pattern_ops
иbpchar_pattern_ops
поддерживают индексы-B-деревья для типовtext
,varchar
иchar
, соответственно. От стандартных классов операторов они отличаются тем, что сравнивают значения по символам, не применяя правила сортировки, определённые локалью. Благодаря этому они подходят для запросов с поиском по шаблону (сLIKE
и регулярными выражениями POSIX), когда локаль базы данных не стандартная «C». Например, вы можете проиндексировать столбецvarchar
так:CREATE INDEX test_index ON test_table (col varchar_pattern_ops);
Заметьте, что при этом также следует создать индекс с классом операторов по умолчанию, если вы хотите ускорить запросы с обычными сравнениями
<
,<=
,>
и>=
за счёт применения индексов. Классы операторов
не подходят для таких сравнений. (Однако для проверки равенств эти классы операторов вполне пригодны.) В подобных случаях для одного столбца можно создать несколько индексов с разными классами операторов. Если же вы используете локаль C, классы операторовxxx
_pattern_ops
вам не нужны, так как для поиска по шаблону в локали C будет достаточно индексов с классом операторов по умолчанию.xxx
_pattern_ops
Следующий запрос выводит список всех существующих классов операторов:
SELECT am.amname AS index_method, opc.opcname AS opclass_name, opc.opcintype::regtype AS indexed_type, opc.opcdefault AS is_default FROM pg_am am, pg_opclass opc WHERE opc.opcmethod = am.oid ORDER BY index_method, opclass_name;
Класс операторов на самом деле является всего лишь подмножеством большой структуры, называемой семейством операторов. В случаях, когда несколько типов данных ведут себя одинаково, часто имеет смысл определить операторы так, чтобы они могли использоваться с индексами сразу нескольких типов. Сделать это можно, сгруппировав классы операторов для этих типов в одном семействе операторов. Такие многоцелевые операторы, являясь членами семейства, не будут связаны с каким-либо одним его классом.
Расширенная версия предыдущего запроса показывает семейство операторов, к которому принадлежит каждый класс операторов:
SELECT am.amname AS index_method, opc.opcname AS opclass_name, opf.opfname AS opfamily_name, opc.opcintype::regtype AS indexed_type, opc.opcdefault AS is_default FROM pg_am am, pg_opclass opc, pg_opfamily opf WHERE opc.opcmethod = am.oid AND opc.opcfamily = opf.oid ORDER BY index_method, opclass_name;
Этот запрос выводит все существующие семейства операторов и все операторы, включённые в эти семейства:
SELECT am.amname AS index_method, opf.opfname AS opfamily_name, amop.amopopr::regoperator AS opfamily_operator FROM pg_am am, pg_opfamily opf, pg_amop amop WHERE opf.opfmethod = am.oid AND amop.amopfamily = opf.oid ORDER BY index_method, opfamily_name, opfamily_operator;
Подсказка
В psql есть команды \dAc
, \dAf
и \dAo
, которые выводят более усовершенствованные версии этих запросов.