Postgres 14.6 上的 Like 查询速度慢

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

我有一个包含 ~ 100.000.000 条记录的表。在此表中,有一个 varchar(30) 列,其中包含汽车牌照。我正在将此表与另一个包含相同数量记录的表连接起来。

我需要使用具有不同值的 like 查询此表,并使用连接表中的列对结果进行排序:

  select *
    from a left join b on a.id = b.id
   where a.license_plate ilike any ('{"GD47%", "CD529%", "CX7530_", "GL573S_"}')
order by b.date

b.date 列上有一个标准索引(btree),a.license_plate 列上有一个 gist 和一个标准 btree 索引。

我仅在类似操作中使用某些值时遇到性能问题。 例如使用这个查询:

  select *
    from a left join b on a.c_id_msg = b.c_id_msg
   where a.c_tar ilike any ('{"AB142%"}')
order by b.date

至少需要20分钟。

性能看起来非常随机,有些值需要几毫秒,有些需要几分钟。 我看到的唯一相关性是,需要较长时间的输入由至少 5 个字符组成,字符串末尾有一个 %。

如果我删除 order by 子句,执行查询只需要几秒钟。

以下是带有 order by 子句和 5 个字符输入的查询的查询规划器结果:

Limit  (cost=1001.16..59950.24 rows=10 width=274)
  ->  Gather Merge  (cost=1001.16..48020923.65 rows=8146 width=274)
        Workers Planned: 2
        ->  Nested Loop  (cost=1.14..48018983.37 rows=3394 width=274)
              ->  Parallel Index Scan Backward using index_btree on b  (cost=0.57..22944880.81 rows=37045867 width=204)
              ->  Index Scan using index_gist on a (cost=0.57..0.68 rows=1 width=70)
                    Index Cond: (c_id_msg = a.c_id_msg)
                    Filter: (((c_tar)::text ~~* ANY ('{AB142%}'::text[])) AND ((c_tip_ric)::text = 'FNL'::text))

此处插入的是没有 order by 子句和 5 个字符输入的查询的查询规划器结果:

Limit  (cost=431.81..565.35 rows=10 width=274)
  ->  Nested Loop  (cost=431.81..109212.18 rows=8146 width=274)
        ->  Bitmap Heap Scan on a (cost=431.24..34898.28 rows=8687 width=70)
              Recheck Cond: ((c_tar)::text ~~* ANY ('{AB142%}'::text[]))
              Filter: ((c_tip_ric)::text = 'FNL'::text)
              ->  Bitmap Index Scan on index_gist  (cost=0.00..429.07 rows=9153 width=0)
                    Index Cond: ((c_tar)::text ~~* ANY ('{AB142%}'::text[]))
        ->  Index Scan using b_pkey on b (cost=0.57..8.55 rows=1 width=204)
              Index Cond: (c_id_msg = a.c_id_msg)

最后,这是带有 order by 子句和 3 个输入字符的查询的查询规划器结果:

Limit  (cost=1001.16..59950.24 rows=10 width=274)
  ->  Gather Merge  (cost=1001.16..48020923.65 rows=8146 width=274)
        Workers Planned: 2
        ->  Nested Loop  (cost=1.14..48018983.37 rows=3394 width=274)
              ->  Parallel Index Scan Backward using index_btree on b  (cost=0.57..22944880.81 rows=37045867 width=204)
              ->  Index Scan using index_gist on a (cost=0.57..0.68 rows=1 width=70)
                    Index Cond: (c_id_msg = a.c_id_msg)
                    Filter: (((c_tar)::text ~~* ANY ('{AB142%}'::text[])) AND ((c_tip_ric)::text = 'FNL'::text))

有没有办法提高此类查询的性能?我是不是做错了什么?

我尝试使用不同的算法添加不同的索引,但结果似乎相同。

sql postgresql indexing postgres-14 gist-index
1个回答
0
投票

尝试使用 CTE,这样排序应该更便宜,例如:

 WITH mydata AS (SELECT a.*,b.date AS bdate 
   FROM a left join b on a.c_id_msg = b.c_id_msg
   WHERE a.c_tar ilike any ('{"AB142%"}') )
 SELECT mydata.* ORDER BY mydata.bdate;
© www.soinside.com 2019 - 2024. All rights reserved.