postgresql" SELECT title FROM table WHERE title ILIKE%keyword%"不使用BTREE INDEX

时间:2016-05-04 12:06:13

标签: sql postgresql utf-8 sql-like

首先我创建表和索引,这里是定义:

    CREATE TABLE boxes(id SERIAL PRIMARY KEY, text text, name character varying(255) COLLATE pg_catalog."C.UTF-8")

    development=# CREATE INDEX boxes_name_idx ON boxes USING btree (name COLLATE pg_catalog."C.UTF-8" varchar_pattern_ops);
    development=# \d boxes
                             Table "public.boxes"
    Column |          Type          |                     Modifiers
    --------+------------------------+----------------------------------------------------
    id     | integer                | not null default nextval('boxes_id_seq'::regclass)
    text   | text                   |
    name   | character varying(255) | collate C.UTF-8
    Indexes:
        "boxes_pkey" PRIMARY KEY, btree (id)
        "boxes_name_idx" btree (name varchar_pattern_ops)

其次,将10003项插入表中,并解释查询。但它变化缓慢:

development=# EXPLAIN ANALYZE SELECT name FROM boxes  WHERE name  ILIKE '%商品%';
                                        QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on boxes  (cost=626.93..1019.21 rows=3 width=87) (actual time=2.356..48.937 rows=3 loops=1)
   Filter: ((name)::text ~~* '%商品%'::text)
   Rows Removed by Filter: 10100
   Heap Blocks: exact=266
   ->  Bitmap Index Scan on boxes_name_idx  (cost=0.00..626.92 rows=10103 width=0) (actual time=1.910..1.910 rows=10103 loops=1)
 Planning time: 0.509 ms
 Execution time: 48.973 ms
    (7 rows)



development=# EXPLAIN ANALYZE SELECT name FROM boxes  WHERE name COLLATE pg_catalog."C.UTF-8"  ILIKE '%商品%';
                                QUERY PLAN
 ---------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on boxes  (cost=626.93..1019.21 rows=3 width=87) (actual time=2.358..49.039 rows=3 loops=1)
   Filter: ((name)::text ~~* '%商品%'::text)
   Rows Removed by Filter: 10100
   Heap Blocks: exact=266
   ->  Bitmap Index Scan on boxes_name_idx  (cost=0.00..626.92 rows=10103 width=0) (actual time=1.896..1.896 rows=10103 loops=1)
 Planning time: 0.506 ms
 Execution time: 49.073 ms
(7 rows)



development=# SELECT name FROM boxes  WHERE name  ILIKE '%商品%';
    name
    -----------
 商品标题3
 商品标题
 商品标题2
 (3 rows)


development=# SELECT count(id) FROM  boxes;
    count
    -------
 10103
(1 row)


development=# SHOW LC_COLLATE;
lc_collate
-------------
en_HK.UTF-8
(1 row)

我们可以看到,索引没有被Filter使用。

我的PostgreSQL版本是9.5.1

1 个答案:

答案 0 :(得分:3)

documentation在这一点上非常明确:

  

优化器也可以使用B树索引进行涉及的查询   模式匹配运算符LIKE和〜如果模式是常量和   锚定在字符串的开头 - 例如col LIKE 'foo%' or col ~ '^foo',但不是col LIKE '%bar'

您的模式以通配符开头。因此,它不使用索引。

Postgres有GIN,GIST和n-gram索引来支持全文支持。