Postgresql - 具有混合大小写或ILike的trigram gin索引的表不使用索引

时间:2017-11-22 02:40:47

标签: postgresql

如果查询中存在混合大小写或ILike,则具有trigram索引的表不起作用。 我不确定我错过了什么。有什么想法吗?

(我正在使用PostgreSQL 9.6.2)

CREATE TABLE public.tbltest (
    "tbltestId" int NOT null ,
    "mystring1" text,
    "mystring2" character varying,  
    CONSTRAINT "tbltest_pkey" PRIMARY KEY ("tbltestId")
);

insert into tbltest ("tbltestId","mystring1", "mystring2")
select x.id, x.id || ' Test', x.id || ' Test' from generate_series(1,100000) AS x(id);

CREATE EXTENSION pg_trgm;

CREATE INDEX tbltest_idx1 ON tbltest using gin ("mystring1" gin_trgm_ops);
CREATE INDEX tbltest_idx2 ON tbltest using gin ("mystring2" gin_trgm_ops);

在查询中使用小写文本,并使用索引

explain analyse 
select * from tbltest 
where "mystring2" Like '%test%';

QUERY PLAN                                                                                                                   |
-----------------------------------------------------------------------------------------------------------------------------|
Bitmap Heap Scan on tbltest  (cost=20.08..56.68 rows=10 width=24) (actual time=29.846..29.846 rows=0 loops=1)                |
  Recheck Cond: ((mystring2)::text ~~ '%test%'::text)                                                                        |
  Rows Removed by Index Recheck: 100000                                                                                      |
  Heap Blocks: exact=726                                                                                                     |
  ->  Bitmap Index Scan on tbltest_idx2  (cost=0.00..20.07 rows=10 width=0) (actual time=12.709..12.709 rows=100000 loops=1) |
        Index Cond: ((mystring2)::text ~~ '%test%'::text)                                                                    |
Planning time: 0.086 ms                                                                                                      |
Execution time: 29.875 ms                                                                                                    |

如果我在搜索中添加混合大小写,则不使用索引

explain analyse 
select * from tbltest 
where "mystring2" Like '%Test%';

QUERY PLAN                                                                                                    |
--------------------------------------------------------------------------------------------------------------|
Seq Scan on tbltest  (cost=0.00..1976.00 rows=99990 width=24) (actual time=0.011..33.376 rows=100000 loops=1) |
  Filter: ((mystring2)::text ~~ '%Test%'::text)                                                               |
Planning time: 0.083 ms                                                                                       |
Execution time: 51.259 ms                                                                                     |

ILike不使用索引

explain analyse 
select * from tbltest 
where "mystring2" ILike '%Test%';

QUERY PLAN                                                                                                    |
--------------------------------------------------------------------------------------------------------------|
Seq Scan on tbltest  (cost=0.00..1976.00 rows=99990 width=24) (actual time=0.012..87.038 rows=100000 loops=1) |
  Filter: ((mystring2)::text ~~* '%Test%'::text)                                                              |
Planning time: 0.134 ms                                                                                       |
Execution time: 105.757 ms                                                                                    |

1 个答案:

答案 0 :(得分:2)

PostgreSQL在最后两个查询中不使用索引,因为这是处理查询的最佳方式,而不是因为它无法使用它。

EXPLAIN输出中,您可以看到第一个查询返回零行(actual ... rows=0),而其他两个查询返回表中的每一行(actual ... rows=100000)。 / p>

PostgreSQL优化器的估算准确地反映了这种情况。

由于它必须访问表的大多数行,PostgreSQL知道如果它按顺序扫描表而不是使用更复杂的索引访问方法,它将能够更便宜地获得结果。