我可以使用带可变字符串的postgres text_pattern_ops索引吗?

问题描述 投票:0回答:1

我正在完善Postgres文本搜索查询,以确保在可能的情况下使用所有可用的索引。我在文本列上有一个text_pattern_obs btree索引,该索引已显示为可以使用简单的查询来工作,例如:

set enable_seqscan = off; -- ensure that indexes are used even on small tables for this demo
select * from search_table where text_column like 'example'

^^这为我提供了使用适当索引的超快速查询。

但是当我想用单个字符串值代替我的'example'文本时,该字符串值是前一个函数或select的结果,它将恢复为完整的顺序表扫描。

with user_input as (select 'example%' as query_string)
select * from search_table, user_input where text_column like query_string

^^这很慢

我尝试过类型转换query_string :: text等,但是没有任何运气。而且我不能只是将字符串直接插入sql中,因为在执行其他查询之前它是未知的。

我正在使用postgres v11,因此应该具有所有最新的查询计划的灵巧性。

sql postgresql full-text-search
1个回答
0
投票

尝试使用准备好的语句而不是联接:

使用:

create table t(x int, y text);
create index fts on t(y text_pattern_ops);
insert into t values(1, 'example');
insert into t values(2, 'examples');
insert into t values(3, 'aaa');
insert into t values(4, 'zzz zzz');
analyze t;
set enable_seqscan = off;

我有:

 select * from t;
     x |    y     
    ---+----------
     1 | example
     2 | examples
     3 | aaa
     4 | zzz zzz
    (4 rows)

   explain analyze select * from t where y like 'example';
                                               QUERY PLAN                                               
--------------------------------------------------------------------------------------------------------
 Index Scan using fts on t  (cost=0.13..8.15 rows=1 width=11) (actual time=0.012..0.013 rows=1 loops=1)
   Index Cond: (y = 'example'::text)
   Filter: (y ~~ 'example'::text)
 Planning Time: 0.111 ms
 Execution Time: 0.030 ms
(5 rows)

explain analyze select * from t where y like 'example%';
                                               QUERY PLAN                                               
--------------------------------------------------------------------------------------------------------
 Index Scan using fts on t  (cost=0.13..8.15 rows=1 width=11) (actual time=0.006..0.007 rows=2 loops=1)
   Index Cond: ((y ~>=~ 'example'::text) AND (y ~<~ 'examplf'::text))
   Filter: (y ~~ 'example%'::text)
 Planning Time: 0.140 ms
 Execution Time: 0.014 ms
(5 rows)

explain analyze with user_input as (select 'example%' as query_string)
select * from t, user_input where y like query_string;
                                                      QUERY PLAN                                                  

------------------------------------------------------------------------------------------------------------------
----
 Nested Loop  (cost=10000000000.01..10000000001.15 rows=1 width=43) (actual time=0.008..0.011 rows=2 loops=1)
   Join Filter: (t.y ~~ user_input.query_string)
   Rows Removed by Join Filter: 2
   CTE user_input
     ->  Result  (cost=0.00..0.01 rows=1 width=32) (actual time=0.001..0.001 rows=1 loops=1)
   ->  Seq Scan on t  (cost=10000000000.00..10000000001.04 rows=4 width=11) (actual time=0.003..0.003 rows=4 loops
=1)
   ->  CTE Scan on user_input  (cost=0.00..0.02 rows=1 width=32) (actual time=0.001..0.001 rows=1 loops=4)
 Planning Time: 0.049 ms
 Execution Time: 0.031 ms
(9 rows)

prepare s1(text) as select * from t where y like $1;
PREPARE
explain analyze execute s1('example%');
                                               QUERY PLAN                                               
--------------------------------------------------------------------------------------------------------
 Index Scan using fts on t  (cost=0.13..8.15 rows=1 width=11) (actual time=0.012..0.014 rows=2 loops=1)
   Index Cond: ((y ~>=~ 'example'::text) AND (y ~<~ 'examplf'::text))
   Filter: (y ~~ 'example%'::text)
 Planning Time: 0.089 ms
 Execution Time: 0.023 ms
(5 rows)
© www.soinside.com 2019 - 2024. All rights reserved.