对于数据库中某个特定表的LIKE个查询,我发现响应时间有很大差异.有时我会在200-400毫秒内得到结果(非常可以接受),但有时可能需要30秒才能返回结果.

我知道LIKE个查询非常耗费资源,但我不明白为什么响应时间会有如此大的差异.我在owner1字段上建立了一个btree索引,但我认为它对LIKE个查询没有帮助.有人有什么 idea 吗?

示例SQL:

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

我也try 过:

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

结果相似

推荐答案

FTS does not support LIKE

previously accepted answer是不正确的.Full Text Search及其全文索引对于LIKE运算符来说是not,它有自己的运算符,不适用于任意字符串.它基于字典和词干分析在words上运行.它支持prefix matching for words,但不支持LIKE操作员:

Trigram index for LIKE

安装额外的模块pg_trgm,该模块为GIN and GiST trigram indexes提供操作员等级,以支持all 102 and 103 patterns,而不仅仅是左锚定的:

示例索引:

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);

查询示例:

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

三角图?短字符串呢?

索引值为less than 3 letters的单词仍然有效.The manual:

每个单词被认为有两个前缀空格和一个空格

搜索少于3个字母的模式?The manual:

对于LIKE和正则表达式搜索,请记住

也就是说,索引/位图索引扫描仍然有效(预处理语句的查询计划不会中断),它不会为您带来更好的性能.通常不会有太大损失,因为1个或2个字母的字符串几乎没有 Select 性(超过基础表匹配的几%),而且索引支持从一开始就不会提高性能,因为全表扫描速度更快.

text_pattern_ops or COLLATE "C" for prefix matching

Update

因为Postgres 9.1,所以COLLATE "C"更好.见:

Original answer

对于left-anchored个模式(没有前导通配符),你可以用一个合适的operator class来表示btree索引:text_pattern_opsvarchar_pattern_ops.这两项都是标准Postgres的内置功能,不需要额外的模块.表现相似,但指数要小得多.

示例索引:

CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);

查询示例:

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

Or,如果您应该使用'C'语言环境(实际上是no语言环境)运行数据库,那么所有内容都是按照字节顺序排序的,使用默认运算符类的普通btree索引就可以完成这项工作.


进一步阅读

Postgresql相关问答推荐

用于JSON数组的带有组合条件的Postgres JSONB Select 查询

处理Ruust-DIESEL中的Jsonb PostgreSQL列

在Postgres游标中从一行变量中减go 另一行变量

PostgreSQL:在 select 和 group by 中使用不同的列不会导致错误

我想优化查询SQL

使用正则表达式计算 SQL 查询中 WHERE 过滤器的数量

无法使用golang在postgresql中使用自定义类型插入/更新数据

PL/pgSQL 中 PL/SQL %ISOPEN 的类似功能是什么?

从dump文件中恢复三张表遇到的问题

DbProviderFactory 与 Npgsql?

!= 和 <> 运算符有什么区别?

如何查询存储在数组中的 Rails ActiveRecord 数据

如果 PostgreSQL 数据库中存在,则删除表

无法登录 PostgreSQL 数据库

判断值是否存在于列中

SQL Select 一列中具有重复值的所有行

安装时 postgres 的默认用户

在 PostgreSQL 中将列数据类型从 Text 更改为 Integer

错误:ERROR: table name specified more than once

判断 Postgres 中是否存在序列(plpgsql)