为什么要在文本列上索引text_pattern_ops?


18

今天,《七周》中的七个数据库向我介绍了每个操作员的索引。

您可以通过创建text_pattern_ops运算符类别索引来为模式与先前查询匹配的字符串建立索引,只要这些值以小写形式索引即可。

CREATE INDEX moves_title_pattern ON movies (
    (lower(title) text_pattern_ops);

我们使用了,text_pattern_ops因为标题是文本类型。如果需要指数VARCHAR处理,字符,或名称,使用相关的OPS: ,varchar_pattern_opsbpchar_pattern_opsname_pattern_ops

我发现该示例确实令人困惑。为什么这样做有用?

如果列是文本类型,在用作搜索值之前,是否会将其他类型(varchar,char,name)强制转换为文本?

该索引的行为与使用默认运算符的索引有何不同?

CREATE INDEX moves_title_pattern ON movies (lower(title));

1
这个相关问题可能会有所帮助:dba.stackexchange.com/questions/10694/…–
Erwin Brandstetter,

谢谢,欧文。在研究书中的思想时,您对这个问题的回答非常有帮助。
Iain Samuel McLean年长者,

Answers:


20

该文档通常为您提供此类问题的答案。也像这种情况

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

CREATE INDEX test_index ON test_table (col varchar_pattern_ops);

请注意,如果希望涉及普通<,<=,>或> =比较的查询使用索引,则还应使用默认的运算符类创建索引。这样的查询不能使用xxx_pattern_ops运算符类。(但是,普通相等性比较可以使用这些运算符类。)可以在具有不同运算符类的同一列上创建多个索引。

该文档继续说:

如果您确实使用C语言环境,则不需要xxx_pattern_ops运算符类,因为具有默认运算符类的索引可用于C语言环境中的模式匹配查询。

您可以按以下方式检查您的语言环境(它可能是UTF8而不是“ C”):

postgres=> show lc_collate;
 lc_collate
-------------
 en_GB.UTF-8

啊哈!我确实读过,但是发现很难理解,所以没有接受。您是否会说有用text_pattern_ops取决于区域设置?看起来这对我有好处,因为我的语言环境是“ en_US.UTF-8”(而不是“ C”),因此模式查询不能使用默认索引。
伊恩·塞缪尔·麦克莱恩

究竟。我要补充一点(但这只是推测),因为数据保留在基本ASCII字符内,默认的运算符类也一样好-至少我看到使用此类索引的LIKE'something%'查询。
dezso

5
@dezso:如果您看到LIKE使用纯b树索引的查询,则数据库必须使用C语言环境。或使用COLLATE "POSIX"(或COLLATE "C")定义索引,并且查询指定匹配项COLLATION。使用任何其他归类,索引的顺序与语言环境规则不匹配,因此不能用于模式匹配。
Erwin Brandstetter,

1
@ErwinBrandstetter我必须确认,你是对的。
dezso 2014年

1
@StopHarmingMonica您将获得正确的响应(并且没有错误),只是查询可能会变慢,无法使用索引。
dezso
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.