我已经看到关于 LIKE
对我数据库中特定表的查询的响应时间有很大的变化。有时我会在 200-400 毫秒内得到结果(非常可接受),但有时可能需要 30 秒才能返回结果。
我知道 LIKE
查询非常耗费资源,但我只是不明白为什么响应时间会有如此大的差异。我在 owner1
字段上建立了一个 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。
原文由 Jason 发布,翻译遵循 CC BY-SA 4.0 许可协议
FTS 不支持
LIKE
先前接受的答案 不正确。带有全文索引的 全文搜索 根本 不适 用于
LIKE
运算符,它有自己的运算符并且不适用于任意字符串。它基于字典和词干对 单词 进行操作。它 确实 支持 _words 的前缀匹配_,但不支持LIKE
运算符:LIKE
安装附加模块
pg_trgm
它为 GIN 和 GiST trigram 索引 提供运算符类以支持 所有LIKE
和ILIKE
模式,而不仅仅是左锚模式:示例索引:
或者:
示例查询:
八卦?较短的字符串呢?
索引值中 少于 3 个字母 的单词仍然有效。 手册:
以及少于 3 个字母的搜索模式? 手册:
意思是,索引/位图索引扫描仍然有效(准备好的语句的查询计划不会中断),它只是不会给你带来更好的性能。通常没有大的损失,因为 1 或 2 字母字符串几乎没有选择性(超过基础表匹配的百分之几),并且索引支持一开始不会提高性能,因为全表扫描更快。
前缀匹配
^@
运算符 /starts_with()
函数引用 Postgres 11 的发行说明:
但是, 在 Postgres 15 中改进了规划器支持 并正确 记录了
^@
运算符 之前,运算符和功能的潜力仍然有限。 发行说明:COLLATE "C"
从 Postgres 9.1 开始,带有
COLLATE "C"
的索引提供了与下面描述的操作符类text_pattern_ops
相同的功能。另见:text_pattern_ops
(原答案)对于 左锚 模式(没有前导通配符),您可以通过合适的 运算符类 为 btree 索引获得最佳值:
text_pattern_ops
或varchar_pattern_ops
。这两个标准 Postgres 的内置功能,不需要额外的模块。性能相似,但索引小得多。示例索引:
示例查询:
_或者_,如果您应该使用 “C” 语言环境(实际上 没有 语言环境)运行数据库,那么无论如何都会根据字节顺序对所有内容进行排序,并且使用默认运算符类的普通 btree 索引可以完成这项工作。
进一步阅读