Uma definição de índice pode especificar uma classe de operadores para cada coluna de um índice.
CREATE INDEXnomeONtabela↵ (colunaopclass↵ [ (opclass_options) ] ↵ [opções de classificação] ↵ [, ...]);
A classe de operadores identifica os operadores a serem usados pelo
índice desta coluna.
Por exemplo, um índice B-Tree no tipo de dados int4
usaria a classe int4_ops;
esta classe de operadores inclui funções de comparação para valores
do tipo de dados int4.
Na prática, a classe de operadores padrão para o tipo de dados da
coluna é geralmente suficiente.
O principal motivo para existirem classes de operadores é que, para
alguns tipos de dados, pode haver mais de um comportamento de índice
significativo.
Por exemplo, podemos querer classificar o tipo de dados número
complexo pelo valor absoluto (módulo), ou pela parte real.
Poderíamos fazer isto definindo duas classes de operadores para o
tipo de dados e, em seguida, selecionando a classe apropriada ao
construir o índice.
A classe de operadores determina a ordem de classificação básica
(que pode ser modificada adicionando as opções de classificação
COLLATE,
ASC/DESC e/ou
NULLS FIRST/NULLS LAST).
Também existem algumas classes de operadores nativas, além das classes que são padrão:
As classes de operadores text_pattern_ops,
varchar_pattern_ops e
bpchar_pattern_ops dão suporte a índices
B-Tree nos tipos de dados text, varchar
e char, respectivamente.
A diferença com relação às classes de operadores padrão, é que os
valores são comparados estritamente caractere por caractere,
em vez de comparar segundo as regras de ordenação
específicas do local.
Esta diferença torna estas classes de operadores adequadas para
uso em consultas envolvendo expressões de correspondência de
padrões (expressões regulares LIKE ou POSIX),
quando o banco de dados não usa a localidade padrão “C”.
Como exemplo, uma coluna varchar pode ser indexada
desta forma:
CREATE INDEX test_index ON test_table (col varchar_pattern_ops);
Note que também deve ser criado um índice com a classe de
operadores padrão, se for desejado que as consultas envolvendo as
comparações comuns <, <=,
>, ou >= usem um índice.
Estas consultas não podem usar as classes de operadores
.
(Entretanto, as comparações de igualdade comuns podem usar estas
classes de operadores.)
É possível criar vários índices na mesma coluna com classes de
operadores diferentes.
Se for usada a localidade C, as classes de operadores
xxx_pattern_ops,
não serão necessárias, porque um índice com a classe de operadores
padrão pode ser usado para consultas de correspondência de padrão
na localidade C.
xxx_pattern_ops
A consulta a seguir mostra as 5 primeiras classes de operadores definidas:
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
LIMIT 5;
index_method | opclass_name | indexed_type | is_default --------------+-------------------+--------------+------------ brin | bit_minmax_ops | bit | t brin | box_inclusion_ops | box | t brin | bpchar_bloom_ops | character | f brin | bpchar_minmax_ops | character | t brin | bytea_bloom_ops | bytea | f (5 linhas)
Uma classe de operadores é, na verdade, apenas um subconjunto de uma estrutura maior chamada família de operadores. Nos casos em que vários tipos de dados têm comportamentos semelhantes, é frequentemente útil definir operadores de tipo de dados cruzados, e permitir que funcionem com índices. Para fazer isto, as classes de operadores para cada um dos tipos de dados devem ser agrupadas na mesma família de operadores. Os operadores de tipo de dados cruzado são membros da família, mas não estão associados a uma única classe na família.
Esta versão expandida da consulta anterior mostra a família de operadores à qual cada classe de operadores pertence:
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
LIMIT 5;
index_method | opclass_name | opfamily_name | indexed_type | is_default --------------+-------------------+-------------------+--------------+------------ brin | bit_minmax_ops | bit_minmax_ops | bit | t brin | box_inclusion_ops | box_inclusion_ops | box | t brin | bpchar_bloom_ops | bpchar_bloom_ops | character | f brin | bpchar_minmax_ops | bpchar_minmax_ops | character | t brin | bytea_bloom_ops | bytea_bloom_ops | bytea | f (5 linhas)
Esta consulta mostra todas as famílias de operadores definidas, e todos os operadores incluídos em cada família:
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
LIMIT 5;
index_method | opfamily_name | opfamily_operator --------------+----------------+------------------- brin | bit_minmax_ops | =(bit,bit) brin | bit_minmax_ops | <(bit,bit) brin | bit_minmax_ops | >(bit,bit) brin | bit_minmax_ops | <=(bit,bit) brin | bit_minmax_ops | >=(bit,bit) (5 linhas)
O psql possui os comandos
\dAc, \dAf e
\dAo, que fornecem versões um pouco mais
sofisticadas destas consultas.