Postgresql

非常簡單的只讀 SELECT 不在 postrgresql 中並行執行

  • June 22, 2018

我正在嘗試在一個大表上做一個簡單的 SELECT,但它沒有並行執行:

my_db=> explain (analyze, buffers) select value from my_table;
Seq Scan on my_table (cost=0.00..94433357.34 rows=5441810434 width=4) (actual time=0.029..1519364.787 rows=4897721407 loops=1)
  Buffers: shared hit=1126394 read=38888859 dirtied=1926396 written=284
Planning time: 2.277 ms
Execution time: 2468388.489 ms

如果我執行 max() 操作,它會並行執行:

my_db=> explain (analyze, buffers) select max(value) from my_table;
Finalize Aggregate  (cost=48552456.41..48552456.42 rows=1 width=4) (actual time=1347796.993..1347796.993 rows=1 loops=1)
  Buffers: shared hit=1173785 read=38870105 dirtied=30813
  ->  Gather  (cost=48552455.58..48552456.39 rows=8 width=4) (actual time=1347796.953..1347796.969 rows=9 loops=1)
        Workers Planned: 8
        Workers Launched: 8
        Buffers: shared hit=1173785 read=38870105 dirtied=30813
        ->  Partial Aggregate  (cost=48551455.58..48551455.59 rows=1 width=4) (actual time=1347790.862..1347790.862 rows=1 loops=9)
              Buffers: shared hit=1172674 read=38870104 dirtied=30813
              ->  Parallel Seq Scan on my_table (cost=0.00..46849720.06 rows=680694206 width=4) (actual time=0.213..1048428.195 rows=544206420 loops=9)
                    Buffers: shared hit=1172674 read=38870104 dirtied=30813
Planning time: 0.761 ms
Execution time: 1347985.127 ms

為什麼 SELECT 不是並行完成的?

該表有數十億行。DBA 做了一些索引——我不知道這到底是什麼意思,但我讀到索引掃描在 PostgreSQL 9.6.8 中不是並行的,但它無論如何都在進行順序掃描。

我在 x86_64-pc-linux-gnu 上使用 PostgreSQL 9.6.8,由 gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9) 編譯,64 位

該表具有以下結構:

my_db=> \d my_table
id       | bigint                         | not null default nextval('my_table_id_seq'::regclass)
datetime | timestamp(0) without time zone | not null
value    | real                           | not null
my_id    | smallint                       | not null
my_flag  | boolean                        | not null

my_db=> \d my_table_id_seq
sequence_name | name    | my_table_id_seq
last_value    | bigint  | 4971842011
start_value   | bigint  | 1
increment_by  | bigint  | 1
max_value     | bigint  | 9223372036854775807
min_value     | bigint  | 1
cache_value   | bigint  | 1
log_cnt       | bigint  | 22
is_cycled     | boolean | f
is_called     | boolean | t

並行 SELECT MAX(value) 仍然需要相當長的時間:

my_db=> \timing on
Timing is on.
my_db=> select max(value) from my_table;
9333

Time: 1342377.208 ms

查詢領導者是唯一與前端通信的程序。查詢的非聚合版本的所有 SELECT 數據都必須從並行工作人員編組到查詢領導者。這很昂貴,因此在這裡使用並行查詢幾乎肯定會適得其反。無論如何,您都可以通過將 parallel_tuple_cost 和 parallel_setup_cost 設置為零來獲得一個。

在進行 count(*) 聚合時,每個並行工作人員只需向領導者發送一條資訊,即部分計數。這顯然更有價值。

引用自:https://dba.stackexchange.com/questions/210205