选择 打开 改范围 完整检索页
受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10
当前 PostgreSQL 版本不在支持生命周期内。
您可以参阅当前版本的对应页面,或其他在上面列出的活跃大版本。

11.10. 操作符类和操作符族 #

索引定义可以为索引的每一列指定一个操作符类

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

操作符类确定索引针对该列使用哪些操作符。例如,建立在类型int4上的 B-树索引会使用int4_ops类;该操作符类包含针对以下类型的值的比较函数:int4。实际中,列数据类型的默认操作符类通常就足够了。之所以需要操作符类,主要是因为对于某些数据类型,可能存在不止一种有意义的索引行为。例如,可能希望按绝对值或实部对复数数据类型排序。可以为该数据类型定义两个操作符类,并在创建索引时选择合适的类。操作符类决定基本排序顺序(随后可以通过添加排序选项进行调整: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;

操作符类其实只是一个更大结构的子集,这个结构称为操作符族。当若干数据类型具有相似行为时,定义跨数据类型操作符并让索引支持它们,往往会很有用。为此,每种类型对应的操作符类都必须归入同一个操作符族。跨类型操作符属于该族,但不与该族中任何单独一个类关联。

前一个查询的扩展版本会显示每个操作符类所属的操作符族:

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;