在postgresql中,哪个部分的语言环境会导致LIKE操作出现问题?

时间:2014-10-20 04:24:12

标签: postgresql locale database-performance

网上有很多关于C或POSIX以外的语言环境的讨论,导致postgresql出现性能问题。我不清楚区域设置的哪个部分会导致问题以及原因。

在initdb(1)的联机帮助页中,我们看到:

--locale=locale
 Sets the default locale for the database cluster. If this option is not specified, the locale is inherited from the environment that
 initdb runs in. Locale support is described in Section 22.1, \u201cLocale Support\u201d, in the documentation.

--lc-collate=locale, --lc-ctype=locale, --lc-messages=locale, --lc-monetary=locale, --lc-numeric=locale, --lc-time=locale
  Like --locale, but only sets the locale in the specified category.

我们也看到了:

   To alter the default collation order or character set classes, use the --lc-collate and --lc-ctype options. Collation orders other than C or
   POSIX also have a performance penalty. For these reasons it is important to choose the right locale when running initdb.

这是否意味着我可以使用--lc-collate POSIX --lc-ctype UTF-8并避免性能损失?或者是否涉及其他性能问题?

我并不感到惊讶,排序规则会影响排序性能,但是LIKE比较不使用索引会产生同样的问题吗?有人可以解释LIKE运算符的问题吗?

1 个答案:

答案 0 :(得分:4)

听起来您正在谈论text_pattern_ops运算符类及其应用于C以外的语言环境中的数据库。

问题不在于编码,而在于整理。

b树索引要求所有内容都遵循一些不变量,具有单个稳定的排序顺序,例如假设a < b然后b > a。比较运算符用于在构建,维护和索引时对树进行排序。

对于文本字符串,比较运算符在确定一个字符串是否大于或小于另一个字符串时应用该语言的校对规则,以便字符串排序&#34;正确&#34;就用户而言。这些规则依赖于语言环境,可以执行忽略标点符号和空格的操作。

LIKE运营商对区域设置不感兴趣。它只是想找到一个前缀字符串,它不能忽略标点符号。因此,它不能使用通过可能忽略标点符号/空格等的排序规则创建的b树索引。LIKE逐字逐句地查找索引树以找到匹配项,并且它无法执行如果索引可能会忽略字符。

这就是为什么,如果您的数据库使用的语言环境不是&#34; C&#34; (POSIX)您必须创建不同的索引以用于LIKE

本地化排序示例,比较:

regress=> WITH x(v) AS (VALUES ('10'),('1'),('1.'),('2.'),('.2'),('.1'),('1-1'),('11')
)
SELECT v FROM x ORDER BY v COLLATE "en_AU";
  v  
-----
 1
 .1
 1.
 10
 11
 1-1
 .2
 2.
(8 rows)

regress=> WITH x(v) AS (VALUES ('10'),('1'),('1.'),('2.'),('.2'),('.1'),('1-1'),('11')
)
SELECT v FROM x ORDER BY v COLLATE "C";
  v  
-----
 .1
 .2
 1
 1-1
 1.
 10
 11
 2.
(8 rows)

text_pattern_ops opclass满足了这一需求。在较新的PostgreSQL版本中,您可以在目标列上创建一个带有COLLATE "C"的索引,但需要满足相同的需求,例如:

CREATE INDEX idx_c ON t2(x COLLATE "C");

LIKE将使用这样的索引,它也可以用于更快的排序,而不必关心给定操作的区域设置,例如

SELECT x FROM t2 ORDER BY x COLLATE "C";