Jas*_*son 103 postgresql indexing query-optimization pattern-matching sql-like
关于LIKE
查询数据库中特定表的响应时间,我看到了相当大的变化.有时我会在200-400毫秒内得到结果(非常可接受),但有时候返回结果可能需要30秒.
我知道LIKE
查询是非常耗费资源的,但我只是不明白为什么响应时间会有这么大的差异.我已经在该owner1
字段上构建了一个btree索引,但我认为这对LIKE
查询没有帮助.有人有主意吗?
示例SQL:
SELECT gid, owner1 FORM parcels
WHERE owner1 ILIKE '%someones name%' LIMIT 10
Run Code Online (Sandbox Code Playgroud)
我也尝试过:
SELECT gid, owner1 FROM parcels
WHERE lower(owner1) LIKE lower('%someones name%') LIMIT 10
Run Code Online (Sandbox Code Playgroud)
和:
SELECT gid, owner1 FROM parcels
WHERE lower(owner1) LIKE lower('someones name%') LIMIT 10
Run Code Online (Sandbox Code Playgroud)
有类似的结果.
表行数:约95,000.
Erw*_*ter 263
LIKE
在以前接受的答案是不正确的.全文搜索及其全文索引根本不适用于LIKE
运算符,它有自己的运算符,不适用于任意字符串.它运行在的话基于字典和制止.它确实支持单词的前缀匹配,但不支持LIKE
运算符:
LIKE
安装附加模块pg_trgm
,该模块为GIN和GiST三元组索引提供运算符类,以支持所有LIKE
和ILIKE
模式,而不仅仅是左锚定模式:
示例索引:
CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);
Run Code Online (Sandbox Code Playgroud)
要么:
CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
Run Code Online (Sandbox Code Playgroud)
示例查询:
SELECT * FROM tbl WHERE col LIKE '%foo%'; -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%'; -- works case insensitively as well
Run Code Online (Sandbox Code Playgroud)
文字少于3个字母的索引值仍然有效.手册:
在确定字符串中包含的三元组时,每个单词被认为有两个空格前缀,一个空格后缀.
搜索模式少于3个字母?手册:
对于两者
LIKE
和正则表达式搜索,请记住,没有可提取三元组的模式将退化为全索引扫描.
意思是,索引/位图索引扫描仍然有效(预备语句的查询计划不会中断),它只是不会给你带来更好的性能.通常没有大的损失,因为单字母或双字母字符串几乎没有选择性(超过基础表匹配的几个百分点)并且索引支持不会提高性能,因为全表扫描更快.
text_pattern_ops
用于前缀匹配对于左锚定模式(没有前导通配符),您可以使用适合btree索引的运算符类获得最佳值:text_pattern_ops
或varchar_pattern_ops
.标准Postgres的内置功能,无需额外的模块.性能相似,但指数要小得多.
示例索引:
CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);
Run Code Online (Sandbox Code Playgroud)
示例查询:
SELECT * FROM tbl WHERE col LIKE 'foo%'; -- no leading wildcard
Run Code Online (Sandbox Code Playgroud)
或者,如果您应该使用'C'语言环境(实际上没有语言环境)运行数据库,那么无论如何都会根据字节顺序对所有内容进行排序,并使用默认运算符类的普通btree索引来完成工作.
dba.SE上这些相关答案的更多细节,解释,示例和链接:
我最近遇到了类似的问题,一个包含 200000 条记录的表,我需要重复执行 LIKE 查询。就我而言,正在搜索的字符串是固定的。其他领域各不相同。因此,我能够重写:
SELECT owner1 FROM parcels
WHERE lower(owner1) LIKE lower('%someones name%');
Run Code Online (Sandbox Code Playgroud)
作为
CREATE INDEX ix_parcels ON parcels(position(lower('someones name') in lower(owner1)));
SELECT owner1 FROM parcels
WHERE position(lower('someones name') in lower(owner1)) > 0;
Run Code Online (Sandbox Code Playgroud)
当查询快速返回并验证索引正在使用时,我很高兴EXPLAIN ANALYZE
:
Bitmap Heap Scan on parcels (cost=7.66..25.59 rows=453 width=32) (actual time=0.006..0.006 rows=0 loops=1)
Recheck Cond: ("position"(lower(owner1), 'someones name'::text) > 0)
-> Bitmap Index Scan on ix_parcels (cost=0.00..7.55 rows=453 width=0) (actual time=0.004..0.004 rows=0 loops=1)
Index Cond: ("position"(lower(owner1), 'someones name'::text) > 0)
Planning time: 0.075 ms
Execution time: 0.025 ms
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
71013 次 |
最近记录: |