在大型 table 上优化 SELECT count(*)
Optimizing SELECT count(*) on large table
在具有 64GB Ram 和 20 个线程的 PostgreSQL 14 上的大型 table 上的基本计数。存储是 NVME 磁盘。
问题:
- 如何改进此 select 计数查询的查询?我应该研究 Postgres 配置的哪些优化?
- 计划的工人是4个,但启动了0个,这正常吗?
EXPLAIN (ANALYZE, BUFFERS)
SELECT count(*) FROM public.product;
Finalize Aggregate (cost=2691545.69..2691545.70 rows=1 width=8) (actual time=330901.439..330902.951 rows=1 loops=1)
Buffers: shared hit=1963080 read=1140455 dirtied=1908 written=111146
I/O Timings: read=36692.273 write=6548.923
-> Gather (cost=2691545.27..2691545.68 rows=4 width=8) (actual time=330901.342..330902.861 rows=1 loops=1)
Workers Planned: 4
Workers Launched: 0
Buffers: shared hit=1963080 read=1140455 dirtied=1908 written=111146
I/O Timings: read=36692.273 write=6548.923
-> Partial Aggregate (cost=2690545.27..2690545.28 rows=1 width=8) (actual time=330898.747..330898.757 rows=1 loops=1)
Buffers: shared hit=1963080 read=1140455 dirtied=1908 written=111146
I/O Timings: read=36692.273 write=6548.923
-> Parallel Index Only Scan using points on products (cost=0.57..2634234.99 rows=22524114 width=0) (actual time=0.361..222958.361 rows=90993600 loops=1)
Heap Fetches: 46261956
Buffers: shared hit=1963080 read=1140455 dirtied=1908 written=111146
I/O Timings: read=36692.273 write=6548.923
Planning:
Buffers: shared hit=39 read=8
I/O Timings: read=0.398
Planning Time: 2.561 ms
JIT:
Functions: 4
Options: Inlining true, Optimization true, Expressions true, Deforming true
Timing: Generation 0.691 ms, Inlining 104.789 ms, Optimization 24.169 ms, Emission 22.457 ms, Total 152.107 ms
Execution Time: 330999.777 ms
The workers planned is 4 but launched 0, is that normal?
当太多并发事务竞争有限数量的允许并行工作程序时,可能会发生这种情况。 The manual:
The number of background workers that the planner will consider using
is limited to at most max_parallel_workers_per_gather
. The
total number of background workers that can exist at any one time is
limited by both max_worker_processes
and
max_parallel_workers
. Therefore, it is possible for a
parallel query to run with fewer workers than planned, or even with no
workers at all. The optimal plan may depend on the number of workers
that are available, so this can result in poor query performance. If
this occurrence is frequent, consider increasing
max_worker_processes
and max_parallel_workers
so that more workers
can be run simultaneously or alternatively reducing
max_parallel_workers_per_gather
so that the planner requests fewer
workers.
您还可以优化整体性能以释放资源或获得更好的硬件(除了提升 max_parallel_workers
)。
同样烦恼的是:
Heap Fetches: 46261956
90993600 行。这是太多的安慰。仅索引扫描不应该执行那么多堆提取。
这两种症状都表明大量并发写入访问(或长运行事务占用资源并使autovacuum
无法完成其工作)。调查一下,and/or 调整每个 table autovacuum
设置 table product
更积极,以便列统计更有效和可见性映射可以跟上。参见:
此外,根据半途有效的 table 统计数据,(快得惊人!)估计 可能就足够了?参见:
- Fast way to discover the row count of a table in PostgreSQL
在具有 64GB Ram 和 20 个线程的 PostgreSQL 14 上的大型 table 上的基本计数。存储是 NVME 磁盘。
问题:
- 如何改进此 select 计数查询的查询?我应该研究 Postgres 配置的哪些优化?
- 计划的工人是4个,但启动了0个,这正常吗?
EXPLAIN (ANALYZE, BUFFERS)
SELECT count(*) FROM public.product;
Finalize Aggregate (cost=2691545.69..2691545.70 rows=1 width=8) (actual time=330901.439..330902.951 rows=1 loops=1)
Buffers: shared hit=1963080 read=1140455 dirtied=1908 written=111146
I/O Timings: read=36692.273 write=6548.923
-> Gather (cost=2691545.27..2691545.68 rows=4 width=8) (actual time=330901.342..330902.861 rows=1 loops=1)
Workers Planned: 4
Workers Launched: 0
Buffers: shared hit=1963080 read=1140455 dirtied=1908 written=111146
I/O Timings: read=36692.273 write=6548.923
-> Partial Aggregate (cost=2690545.27..2690545.28 rows=1 width=8) (actual time=330898.747..330898.757 rows=1 loops=1)
Buffers: shared hit=1963080 read=1140455 dirtied=1908 written=111146
I/O Timings: read=36692.273 write=6548.923
-> Parallel Index Only Scan using points on products (cost=0.57..2634234.99 rows=22524114 width=0) (actual time=0.361..222958.361 rows=90993600 loops=1)
Heap Fetches: 46261956
Buffers: shared hit=1963080 read=1140455 dirtied=1908 written=111146
I/O Timings: read=36692.273 write=6548.923
Planning:
Buffers: shared hit=39 read=8
I/O Timings: read=0.398
Planning Time: 2.561 ms
JIT:
Functions: 4
Options: Inlining true, Optimization true, Expressions true, Deforming true
Timing: Generation 0.691 ms, Inlining 104.789 ms, Optimization 24.169 ms, Emission 22.457 ms, Total 152.107 ms
Execution Time: 330999.777 ms
The workers planned is 4 but launched 0, is that normal?
当太多并发事务竞争有限数量的允许并行工作程序时,可能会发生这种情况。 The manual:
The number of background workers that the planner will consider using is limited to at most
max_parallel_workers_per_gather
. The total number of background workers that can exist at any one time is limited by bothmax_worker_processes
andmax_parallel_workers
. Therefore, it is possible for a parallel query to run with fewer workers than planned, or even with no workers at all. The optimal plan may depend on the number of workers that are available, so this can result in poor query performance. If this occurrence is frequent, consider increasingmax_worker_processes
andmax_parallel_workers
so that more workers can be run simultaneously or alternatively reducingmax_parallel_workers_per_gather
so that the planner requests fewer workers.
您还可以优化整体性能以释放资源或获得更好的硬件(除了提升 max_parallel_workers
)。
同样烦恼的是:
Heap Fetches: 46261956
90993600 行。这是太多的安慰。仅索引扫描不应该执行那么多堆提取。
这两种症状都表明大量并发写入访问(或长运行事务占用资源并使autovacuum
无法完成其工作)。调查一下,and/or 调整每个 table autovacuum
设置 table product
更积极,以便列统计更有效和可见性映射可以跟上。参见:
此外,根据半途有效的 table 统计数据,(快得惊人!)估计 可能就足够了?参见:
- Fast way to discover the row count of a table in PostgreSQL