1

我在 RHEL 5.8 操作系统上运行 postgresql-9.1.6。我得到了一个实现 seq 扫描的语句,该语句对哪一列进行了索引。

                          Table "public.table"
Column    |         Type          |                Modifiers                
----------+-----------------------+-----------------------------------------
 col1     | character(3)          | not null
 col2     | character varying(20) | not null
 col3     | character varying(20) | 
 col4     | character(1)          | default 0
Indexes:
    "table_pkey" PRIMARY KEY, btree (col1, col2)


postgres=# explain analyze select * from table where col1=right('10000081',3);
                                                      QUERY PLAN                                                      
----------------------------------------------------------------------------------------------------------------------
 Seq Scan on table  (cost=0.00..31053.24 rows=5650 width=286) (actual time=3.221..429.950 rows=110008 loops=1)
   Filter: ((col1)::text = '081'::text)
 Total runtime: 435.904 ms
(3 rows)

postgres=# explain analyze select * from table where col1=right('10000081',3)::char(3);
                                                               QUERY PLAN                                                                
-----------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on table  (cost=3097.81..18602.98 rows=112173 width=286) (actual time=18.125..32.707 rows=110008 loops=1)
   Recheck Cond: (col1 = '081'::character(3))
   ->  Bitmap Index Scan on table_pkey  (cost=0.00..3069.77 rows=112173 width=0) (actual time=17.846..17.846 rows=110008 loops=1)
         Index Cond: (col1 = '081'::character(3))
 Total runtime: 38.640 ms
(5 rows)

我发现 [alter column] 是解决方案之一....

postgres=# alter table table alter column col1 type varchar(3);               
ALTER TABLE
postgres=# explain analyze select * from table where col1=right('10000081',3);
                                                              QUERY PLAN                                                              
--------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on table  (cost=160.26..10902.32 rows=5650 width=295) (actual time=20.249..41.658 rows=110008 loops=1)
   Recheck Cond: ((col1)::text = '081'::text)
   ->  Bitmap Index Scan on table_pkey  (cost=0.00..158.85 rows=5650 width=0) (actual time=20.007..20.007 rows=110008 loops=1)
         Index Cond: ((col1)::text = '081'::text)
 Total runtime: 47.408 ms
(5 rows)

我想知道为什么?

4

2 回答 2

4

从第一个计划中可以看出,在 col1 上执行了隐式类型转换以匹配right()的返回类型。

Filter: ((col1)::text = '081'::text)

显然,表达式 right('10000081',3) 返回文本。

所以我会说是的,你必须输入表达式,尽管另一种方法是在 (col1)::text 上建立索引——虽然不是我最喜欢的解决方案。

于 2013-06-04T09:21:35.797 回答
3

避免char数据类型。这很糟糕,原因有很多,这只是其中之一。

如果你坚持,text否则varchar你会遇到更少的隐式强制转换和令人困惑的行为的问题。

于 2013-06-04T12:15:14.133 回答