使用多个“介于”条件的优化查询

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

我有一个具有列playground的表val,对列val进行了索引。

我有一个范围列表[(min1, max1), (min2, max2), ... , (minN, maxN)]并且我想选择val的所有行都适合任何这些范围。

例如我的范围如下所示:[(1,5), (20,25), (200,400)]这是提取相应行的简单查询:

select p.*
from playground p
where (val between 1 AND 5) or (val between 20 and 25) or
    (val between 200 and 400);

这里的问题是,该范围列表是动态的,我的应用程序生成了该列表并将其与查询一起发送到postgres。

我试图重写查询以接受动态范围列表:

select p.*
from playground p,
    unnest(ARRAY [(1, 5),(20, 25),(200, 400)]) as r(min_val INT, max_val INT)
where p.val between r.min_val and r.max_val;

它提取相同的行,但我不知道这是一个有效的方法吗?

这是第一个查询的说明:

Bitmap Heap Scan on playground p  (cost=12.43..16.45 rows=1 width=36) (actual time=0.017..0.018 rows=4 loops=1)
  Recheck Cond: (((val >= 1) AND (val <= 5)) OR ((val >= 20) AND (val <= 25)) OR ((val >= 200) AND (val <= 400)))
  Heap Blocks: exact=1
  ->  BitmapOr  (cost=12.43..12.43 rows=1 width=0) (actual time=0.012..0.012 rows=0 loops=1)
        ->  Bitmap Index Scan on playground_val_index  (cost=0.00..4.14 rows=1 width=0) (actual time=0.010..0.010 rows=3 loops=1)
              Index Cond: ((val >= 1) AND (val <= 5))
        ->  Bitmap Index Scan on playground_val_index  (cost=0.00..4.14 rows=1 width=0) (actual time=0.001..0.001 rows=0 loops=1)
              Index Cond: ((val >= 20) AND (val <= 25))
        ->  Bitmap Index Scan on playground_val_index  (cost=0.00..4.14 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1)
              Index Cond: ((val >= 200) AND (val <= 400))
Planning Time: 0.071 ms
Execution Time: 0.057 ms

这是第二个的解释:

Nested Loop  (cost=0.14..12.52 rows=2 width=36) (actual time=0.033..0.065 rows=4 loops=1)
  ->  Function Scan on unnest r  (cost=0.00..0.03 rows=3 width=8) (actual time=0.011..0.012 rows=3 loops=1)
  ->  Index Scan using playground_val_index on playground p  (cost=0.13..4.15 rows=1 width=36) (actual time=0.008..0.015 rows=1 loops=3)
        Index Cond: ((val >= r.min_val) AND (val <= r.max_val))
Planning Time: 0.148 ms
Execution Time: 0.714 ms

注意:在两种情况下,我都set enable_seqscan = false;使索引起作用。

我担心“嵌套循环”阶段。可以吗还是有更有效的方法将范围的动态列表传递到查询中?我的postgres版本是12.1

sql postgresql select postgresql-performance
1个回答
0
投票

您添加了更多信息,但是还有更多相关信息。精确的表和索引定义,基数,数据分布,行大小统计信息,谓词的范围数,表的用途,写入模式等...性能优化需要它可以获得的所有输入。

© www.soinside.com 2019 - 2024. All rights reserved.