Rab*_*yal 3 sql postgresql indexing database-design pattern-matching
我有一个用户表,它包含位置列。我使用 varchar_pattern_ops 索引了位置列。但是当我运行查询规划器时,它告诉我它正在执行顺序扫描。
EXPLAIN ANALAYZE
SELECT * FROM USERS
WHERE lower(location) like '%nepa%'
ORDER BY location desc;
Run Code Online (Sandbox Code Playgroud)
它给出以下结果:
Sort (cost=12.41..12.42 rows=1 width=451) (actual time=0.084..0.087 rows=8 loops=1)
Sort Key: location
Sort Method: quicksort Memory: 27kB
-> Seq Scan on users (cost=0.00..12.40 rows=1 width=451) (actual time=0.029..0.051 rows=8 loops=1)
Filter: (lower((location)::text) ~~ '%nepa%'::text)
Planning time: 0.211 ms
Execution time: 0.147 ms
Run Code Online (Sandbox Code Playgroud)
我已经通过 stackoverflow 进行了搜索。发现大多数答案都类似于“postgres 在大表中执行顺序扫描,以防索引扫描速度变慢”。但我的桌子也不大。
我表中的索引users是:
"index_users_on_lower_location_varchar_pattern_ops" btree (lower(location::text) varchar_pattern_ops)
Run Code Online (Sandbox Code Playgroud)
到底是怎么回事?
*_patter_ops索引适合前缀匹配-LIKE锚定到开头的模式,没有前导通配符。但不适用于您的谓词:
WHERE lower(location) like '%nepa%'
Run Code Online (Sandbox Code Playgroud)
我建议改用三元组索引。您不需要lower()索引(或查询),因为三元组索引以几乎相同的成本支持不区分大小写ILIKE(或)。~*
请按照此处的说明操作:
还:
但我的桌子也不大。
你好像搞反了。如果你的表不够大,Postgres 直接按顺序读取它而不用担心索引会更快。您根本不会创建任何索引。临界点取决于许多因素。
您的索引定义一开始就没有意义:
(lower(location::text) varchar_pattern_ops)
Run Code Online (Sandbox Code Playgroud)
对于varchar列,请使用varchar_pattern_ops运算符类。
但即使输入lower()也会返回,因此请使用. 但正如建议的那样,您可能根本不需要这个(或任何?)索引。
如果您仍然认为需要该索引,请考虑使用索引。看:textvarchartext_pattern_opsCOLLATE "C"
| 归档时间: |
|
| 查看次数: |
2374 次 |
| 最近记录: |