11.10. 运算符类别和运算符家族

索引定义可以为索引的每一列指定一个* operator class *。

CREATE INDEX name ON table (column opclass [sort options] [, ...]);

operator 类标识该列的索引要使用的运算符。例如,类型为int4的 B 树索引将使用int4_ops类;此运算符类包含类型为int4的值的比较函数。实际上,列数据类型的默认运算符类通常就足够了。具有运算符类的主要原因是,对于某些数据类型,可能存在多个有意义的索引行为。例如,我们可能想按绝对值或实数对复数数据类型进行排序。为此,我们可以为数据类型定义两个运算符类,然后在创建索引时选择适当的类。操作员类别确定基本的排序 Sequences(然后可以通过添加排序选项COLLATEASC/DESC和/或NULLS FIRST/NULLS LAST进行修改)。

除了默认值之外,还有一些内置的运算符类:

  • 运算符类text_pattern_opsvarchar_pattern_opsbpchar_pattern_ops分别支持textvarcharchar类型的 B 树索引。与默认运算符类的不同之处在于,将严格按字符对值进行比较,而不是根据特定于语言环境的整理规则进行比较。当数据库不使用标准“ C”语言环境时,这使这些运算符类适用于涉及模式匹配表达式(LIKE或 POSIX 正则表达式)的查询。例如,您可以像这样对varchar列构建索引:
CREATE INDEX test_index ON test_table (col varchar_pattern_ops);

请注意,如果希望涉及普通<<=>>=比较的查询使用索引,则还应该使用默认的运算符类创建索引。这样的查询不能使用xxx_pattern_ops运算符类。 (但是,普通相等性比较可以使用这些运算符类.)可以在具有不同运算符类的同一列上创建多个索引。如果确实使用 C 语言环境,则不需要xxx_pattern_ops运算符类,因为具有默认运算符类的索引可用于 C 语言环境中的模式匹配查询。

以下查询显示所有已定义的运算符类:

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;

运算符类实际上只是一个更大的结构的子集,称为* operator family *。在几种数据类型具有相似行为的情况下,定义跨数据类型运算符并允许它们与索引一起使用通常很有用。为此,必须将每种类型的操作员类别归为同一操作员族。交叉类型运算符是该家族的成员,但与该家族中的任何单个类别都不相关。

上一个查询的扩展版本显示了每个操作员类别所属的操作员家族:

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;