postgres(如“…%”)不使用索引

iszxjhcz  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(322)

我有一个表,我想在其中搜索一个前缀的主键。主键的值如下 03.000221.1 , 03.000221.2 , 03.000221.3 等等,我想从 03.000221. .
我的第一个想法是用 LIKE '03.000221.%' ,以为博士后会聪明到抬头看看 03.000221. 并从该点执行范围扫描。但不是,这是一个顺序扫描。

QUERY PLAN                                                    
-----------------------------------------------------------------------------------------------------------------
 Gather  (cost=1000.00..253626.34 rows=78 width=669)
   Workers Planned: 2
   ->  Parallel Seq Scan on ...  (cost=0.00..252618.54 rows=32 width=669)
         Filter: ((id ~~ '03.000221.%'::text)
 JIT:
   Functions: 2
   Options: Inlining false, Optimization false, Expressions true, Deforming true

如果我用一个普通的 >= 以及 < 范围,e。g。 id >= '03.000221.' and id < '03.000221.Z' 它确实使用索引:

QUERY PLAN                                                                  
---------------------------------------------------------------------------------------------------------------------------------------------
 Index Scan using ... on ...  (cost=0.56..8.58 rows=1 width=669)
   Index Cond: ((id >= '03.000221.'::text) AND (id < '03.000221.Z'::text))

但这更脏,在我看来,postgres应该能够推断出它可以使用 LIKE . 为什么不呢?

zed5wv10

zed5wv101#

如果您是使用文本\模式\ ops运算符构建索引,或者使用c排序规则,postgresql将执行此操作。
如果您使用的是一些随机的其他排序规则,那么postgresql无法推断出关于它的很多信息。在非常常见的“en\u us.utf8”排序规则中,请注意这一点。

select * from (values ('03.000221.1'), ('03.0002212'), ('03.000221.3')) f(x) order by x;
      x      
-------------
 03.000221.1
 03.0002212
 03.000221.3

这就自然而然地导致了你的问题的错误答案:

select * from (values ('03.000221.1'), ('03.0002212'), ('03.000221.3')) f(id)
    where ((id >= '03.000221.'::text) AND (id < '03.000221.Z'::text))
     id      
-------------
 03.000221.1
 03.0002212
 03.000221.3

相关问题