PostgreSQL LIKE查询性能变化

我已经看到在我的数据库中的特定表LIKE查询响应时间相当大的变化。 有时我会在200-400毫秒(非常可接受的)内得到结果,但有些时候可能需要多达30秒才能返回结果。

我知道LIKE查询是非常耗费资源的,但我不明白为什么会有这么大的响应时间差异。 我已经在owner1字段上构build了一个btree索引,但我不认为这对LIKE查询有帮助。 任何人有任何想法?

示例SQL:

 SELECT gid, owner1 FORM parcels WHERE owner1 ILIKE '%someones name%' LIMIT 10 

我也试过:

 SELECT gid, owner1 FROM parcels WHERE lower(owner1) LIKE lower('%someones name%') LIMIT 10 

和:

 SELECT gid, owner1 FROM parcels WHERE lower(owner1) LIKE lower('someones name%') LIMIT 10 

有类似的结果。
表行数:约95,000。

FTS不支持LIKE

以前接受的答案是不正确的。 具有全文索引的全文本search根本不适用于LIKE运算符,它具有自己的运算符,不适用于任意string。 它运行在词典和词干的基础上。 它支持字的前缀匹配 ,但不支持LIKE运算符:

  • 从GIN索引TSVECTOR列获得部分匹配

LIKE Trigram索引

安装附加模块pg_trgm ,它为GIN和GiST三字节索引提供运算符类,以支持所有的LIKEILIKE模式 ,而不仅仅是左侧的模式

示例索引:

 CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops ); 

要么:

 CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops ); 
  • GiST和GIN指数的区别

示例查询:

 SELECT * FROM tbl WHERE col LIKE '%foo%'; -- leading wildcard SELECT * FROM tbl WHERE col ILIKE '%foo%'; -- works case insensitively as well 

text_pattern_ops用于前缀匹配

对于左锚模式(无引导通配符),您可以使用适合btree索引的操作符类 : text_pattern_opsvarchar_pattern_ops获得最佳效果。 标准Postgres的两个内置function,不需要额外的模块。 相似的performance,但是指数要小得多。

示例索引:

 CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops ); 

示例查询:

 SELECT * FROM tbl WHERE col LIKE 'foo%' ; -- no leading wildcard 

或者 ,如果您应该使用“C”语言环境(实际上没有语言环境)来运行数据库,则无论如何,所有内容都按照字节顺序进行sorting,而具有默认操作符类的普通btree索引完成这项工作。

有关dba.SE的相关答案的更多细节,解释,示例和链接:

  • 在PostgreSQL中与LIKE,SIMILAR TO或正则expression式匹配的模式
  • LIKE是如何实现的?
  • 用PostgreSQL快速find类似的string

可能是快速的那些锚定模式,如可以使用索引的区分大小写。 即在匹配string的开头没有通配符,因此执行者可以使用索引范围扫描。 ( 文档中的相关评论在这里 )如果您专门为此目的创build了一个索引(请参阅函数索引 ),则较低和ilike也将失去使用该索引的能力。

如果要在字段中间searchstring,则应查看全文或三字节索引 。 首先是在Postgres核心,另一个在contrib模块中可用。

您可以在PostgreSQL中安装Wildspeed ,这是一种不同types的索引。 Wildspeed可以使用%word%通配符,没问题。 缺点是指数的大小,这可能很大,非常大。

请执行下面提到的查询来提高postgresql中的LIKE查询性能。 为更大的表创build一个像这样的索引:

 CREATE INDEX <indexname> ON <tablename> USING btree (<fieldname> text_pattern_ops) 

你的查询可能不能使用你创build的索引,因为:

1)你的LIKE标准以通配符开始。

2)你已经使用了LIKE标准的函数。