postgresql postgres查询慢性能:不快于支柱相等

s4chpxco  于 2022-12-18  发布在  PostgreSQL
关注(0)|答案(2)|浏览(153)

所以我在一个很大的表上有这个查询:

SELECT * FROM datTable WHERE type='bla' 
AND timestamp > (CURRENT_DATE - INTERVAL '1 day')

这个查询太慢了,大概5秒钟;并且type上有一个索引
所以我试着:

SELECT * FROM datTable WHERE type NOT IN ('blu','bli','blo') 
AND timestamp > (CURRENT_DATE - INTERVAL '1 day')

这个查询比1 second好得多,但问题是我不想硬编码这个not type列表。
所以我试着:

with res as (
    SELECT * FROM datTable WHERE type NOT IN ('blu','bli','blo') 
    AND timestamp > (CURRENT_DATE - INTERVAL '1 day')
)
select * from res where type='bla'


我又回到了糟糕的表现,5秒和以前一样。
你知道我如何欺骗postgres获得1 sec perf,但明确指定我想要的type(“bla”)吗?

编辑:EXPLAIN ANALYZE用于最后一次请求

GroupAggregate  (cost=677400.59..677493.09 rows=3595 width=59) (actual time=4789.667..4803.183 rows=3527 loops=1)
  Group Key: event_historic.sender
  ->  Sort  (cost=677400.59..677412.48 rows=4756 width=23) (actual time=4789.646..4792.808 rows=68045 loops=1)
        Sort Key: event_historic.sender
        Sort Method: quicksort  Memory: 9469kB
        ->  Bitmap Heap Scan on event_historic  (cost=505379.21..677110.11 rows=4756 width=23) (actual time=4709.494..4769.437 rows=68045 loops=1)
              Recheck Cond: (("timestamp" > (CURRENT_DATE - '1 day'::interval)) AND ((type)::text = 'NEAR_TRANSFER'::text))
              Heap Blocks: exact=26404
              ->  BitmapAnd  (cost=505379.21..505379.21 rows=44676 width=0) (actual time=4706.080..4706.082 rows=0 loops=1)
                    ->  Bitmap Index Scan on event_historic_timestamp_idx  (cost=0.00..3393.89 rows=263109 width=0) (actual time=167.838..167.838 rows=584877 loops=1)
                          Index Cond: ("timestamp" > (CURRENT_DATE - '1 day'::interval))
                    ->  Bitmap Index Scan on event_historic_type_idx  (cost=0.00..501982.69 rows=45316549 width=0) (actual time=4453.071..4453.071 rows=44279973 loops=1)
                          Index Cond: ((type)::text = 'NEAR_TRANSFER'::text)
Planning Time: 0.385 ms
JIT:
  Functions: 10
  Options: Inlining true, Optimization true, Expressions true, Deforming true
  Timing: Generation 2.505 ms, Inlining 18.102 ms, Optimization 87.745 ms, Emission 44.270 ms, Total 152.622 ms
Execution Time: 4809.099 ms

编辑2:在(类型,时间戳)上添加索引后,结果会更快:

HashAggregate  (cost=156685.88..156786.59 rows=8057 width=59) (actual time=95.201..96.511 rows=3786 loops=1)
  Group Key: sender
  Batches: 1  Memory Usage: 2449kB
  Buffers: shared hit=31041
  ->  Index Scan using typetimestamp on event_historic eh  (cost=0.57..156087.67 rows=47857 width=44) (actual time=12.244..55.921 rows=76220 loops=1)
        Index Cond: (((type)::text = 'NEAR_TRANSFER'::text) AND ("timestamp" > (CURRENT_DATE - '1 day'::interval)))
        Buffers: shared hit=31041
Planning:
  Buffers: shared hit=5
Planning Time: 0.567 ms
JIT:
  Functions: 10
  Options: Inlining false, Optimization false, Expressions true, Deforming true
  Timing: Generation 2.543 ms, Inlining 0.000 ms, Optimization 1.221 ms, Emission 10.819 ms, Total 14.584 ms
Execution Time: 99.496 ms
kiayqfof

kiayqfof1#

您需要在((type::text), timestamp)上建立一个两列索引以加快查询速度。
让我详细解释一下索引顺序背后的原因,如果type是索引中的第一个,索引扫描可以从('NEAR_TRANSFER', <now - 1 day>)之后的第一个索引条目开始,扫描所有索引条目,直到它命中下一个type,这样找到的所有索引条目都对应于一个结果行。扫描必须从(<now - 1 day>, ...)之后的第一个条目开始,读取所有索引条目,直到索引末尾。它将丢弃type IS DISTINCT FROM 'NEAR_TRANSFER'处的索引条目,并为其余索引条目获取表行。因此,此扫描将获取相同数量的表行,但必须读取更多索引条目。
选择性最强的列应该是索引中的第一列,这是一个古老的神话,但它仍然是一个神话。由于上述原因,您应该将与=进行比较的列放在索引中的第一列。列的选择性是无关紧要的。
所有这些都是孤立地谈论单个查询,但是您总是必须考虑工作负载中的所有其他查询,对于它们来说,列的排序方式可能会有所不同。

vxf3dgd4

vxf3dgd42#

时间戳和类型的单个索引可能更快:

CREATE INDEX idx1 ON datTable (timestamp, type);

或者:

CREATE INDEX idx1 ON datTable (type, timestamp);

如果使用了新索引,请检查查询计划。也许还必须删除旧索引。而且很可能无论如何都可以删除旧索引。

相关问题