Re: Append with naive multiplexing of FDWs - Mailing list pgsql-hackers
From | Kyotaro Horiguchi |
---|---|
Subject | Re: Append with naive multiplexing of FDWs |
Date | |
Msg-id | 20191212.214057.2013694839251103876.horikyota.ntt@gmail.com Whole thread Raw |
In response to | Re: Append with naive multiplexing of FDWs (Bruce Momjian <bruce@momjian.us>) |
Responses |
Re: Append with naive multiplexing of FDWs
|
List | pgsql-hackers |
Hello. I think I can say that this patch doesn't slows non-AsyncAppend, non-postgres_fdw scans. At Mon, 9 Dec 2019 12:18:44 -0500, Bruce Momjian <bruce@momjian.us> wrote in > Certainly any overhead on normal queries would be unacceptable. I took performance numbers on the current shape of the async execution patch for the following scan cases. t0 : single local table (parallel disabled) pll : local partitioning (local Append, parallel disabled) ft0 : single foreign table pf0 : inheritance on 4 foreign tables, single connection pf1 : inheritance on 4 foreign tables, 4 connections ptf0 : partition on 4 foreign tables, single connection ptf1 : partition on 4 foreign tables, 4 connections The benchmarking system is configured as the follows on a single machine. [ benchmark client ] | | (localhost:5433) (localhost:5432) | | +----+ | +------+ | | V V V | V | [master server] | [async server] | V | V +--fdw--+ +--fdw--+ The patch works roughly in the following steps. 1. Planner decides how many children out of an append can run asynchrnously (called as async-capable.). 2. While ExecInit if an Append doesn't have an async-capable children, ExecAppend that is exactly the same function is set as ExecProcNode. Otherwise ExecAppendAsync is used. If the infrastructure part in the patch causes any degradation, the "t0"(scan on local single table) and/or "pll" test (scan on a local paritioned table) gets slow. 3. postgresql_fdw always runs async-capable code path. If the postgres_fdw part causes degradation, ft0 reflects that. The tables has two integers and the query does sum(a) on all tuples. With the default fetch_size = 100, number is run time in ms. Each number is the average of 14 runs. master patched gain t0 7325 7130 +2.7% pll 4558 4484 +1.7% ft0 3670 3675 -0.1% pf0 2322 1550 +33.3% pf1 2367 1475 +37.7% ptf0 2517 1624 +35.5% ptf1 2343 1497 +36.2% With larger fetch_size (200) the gain mysteriously decreases for sharing single connection cases (pf0, ptf0), but others don't seem change so much. master patched gain t0 7212 7252 -0.6% pll 4546 4397 +3.3% ft0 3712 3731 -0.5% pf0 2131 1570 +26.4% pf1 1926 1189 +38.3% ptf0 2001 1557 +22.2% ptf1 1903 1193 +37.4% FWIW, attached are the test script. gentblr2.sql: Table creation script. testrun.sh : Benchmarking script. regards. -- Kyotaro Horiguchi NTT Open Source Software Center SELECT :scale * 0 as th0, :scale * 1 as th1, :scale * 2 as th2, :scale * 3 as th3, :scale * 4 as th4, :scale * 10 as th10, :scale * 20 as th20, :scale * 30 as th30, :scale * 40 as th40, :scale * 100 as th100, :scale * 1000 as th1000 \gset DROP TABLE IF EXISTS t0 CASCADE; DROP TABLE IF EXISTS pl CASCADE; DROP TABLE IF EXISTS pll CASCADE; DROP TABLE IF EXISTS pf0 CASCADE; DROP TABLE IF EXISTS pf1 CASCADE; DROP TABLE IF EXISTS ptf0; DROP TABLE IF EXISTS ptf1; CREATE TABLE pl (a int, b int); CREATE TABLE cl1 (LIKE pl) INHERITS (pl); CREATE TABLE cl2 (LIKE pl) INHERITS (pl); CREATE TABLE cl3 (LIKE pl) INHERITS (pl); CREATE TABLE cl4 (LIKE pl) INHERITS (pl); INSERT INTO cl1 (SELECT a, a FROM generate_series(:th0, :th1 - 1) a); INSERT INTO cl2 (SELECT a, a FROM generate_series(:th1, :th2 - 1) a); INSERT INTO cl3 (SELECT a, a FROM generate_series(:th2, :th3 - 1) a); INSERT INTO cl4 (SELECT a, a FROM generate_series(:th3, :th4 - 1) a); CREATE TABLE pll (a int, b int); CREATE TABLE cll1 (LIKE pl) INHERITS (pll); CREATE TABLE cll2 (LIKE pl) INHERITS (pll); CREATE TABLE cll3 (LIKE pl) INHERITS (pll); CREATE TABLE cll4 (LIKE pl) INHERITS (pll); INSERT INTO cll1 (SELECT a, a FROM generate_series(:th0, :th10 - 1) a); INSERT INTO cll2 (SELECT a, a FROM generate_series(:th10, :th20 - 1) a); INSERT INTO cll3 (SELECT a, a FROM generate_series(:th20, :th30 - 1) a); INSERT INTO cll4 (SELECT a, a FROM generate_series(:th30, :th40 - 1) a); CREATE TABLE t0 (LIKE pl); INSERT INTO t0 (SELECT a, a FROM generate_series(0, :th100 - 1) a); DROP SERVER IF EXISTS svl CASCADE; DROP SERVER IF EXISTS sv0 CASCADE; DROP SERVER IF EXISTS sv1 CASCADE; DROP SERVER IF EXISTS sv2 CASCADE; DROP SERVER IF EXISTS sv3 CASCADE; DROP SERVER IF EXISTS sv4 CASCADE; CREATE SERVER svl FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host :'svhost', port :'svport', dbname :'svdbname', fetch_size:'fetchsize'); CREATE SERVER sv0 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host :'svhost', port :'svport', dbname :'svdbname', fetch_size:'fetchsize'); CREATE SERVER sv1 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host :'svhost', port :'svport', dbname :'svdbname', fetch_size:'fetchsize'); CREATE SERVER sv2 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host :'svhost', port :'svport', dbname :'svdbname', fetch_size:'fetchsize'); CREATE SERVER sv3 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host :'svhost', port :'svport', dbname :'svdbname', fetch_size:'fetchsize'); CREATE SERVER sv4 FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host :'svhost', port :'svport', dbname :'svdbname', fetch_size:'fetchsize'); CREATE USER MAPPING FOR public SERVER svl; CREATE USER MAPPING FOR public SERVER sv0; CREATE USER MAPPING FOR public SERVER sv1; CREATE USER MAPPING FOR public SERVER sv2; CREATE USER MAPPING FOR public SERVER sv3; CREATE USER MAPPING FOR public SERVER sv4; CREATE FOREIGN TABLE ft0 (a int, b int) SERVER svl OPTIONS (table_name 't0'); CREATE FOREIGN TABLE ft10 (a int, b int) SERVER sv0 OPTIONS (table_name 'cl1'); CREATE FOREIGN TABLE ft20 (a int, b int) SERVER sv0 OPTIONS (table_name 'cl2'); CREATE FOREIGN TABLE ft30 (a int, b int) SERVER sv0 OPTIONS (table_name 'cl3'); CREATE FOREIGN TABLE ft40 (a int, b int) SERVER sv0 OPTIONS (table_name 'cl4'); CREATE FOREIGN TABLE ft11 (a int, b int) SERVER sv1 OPTIONS (table_name 'cl1'); CREATE FOREIGN TABLE ft22 (a int, b int) SERVER sv2 OPTIONS (table_name 'cl2'); CREATE FOREIGN TABLE ft33 (a int, b int) SERVER sv3 OPTIONS (table_name 'cl3'); CREATE FOREIGN TABLE ft44 (a int, b int) SERVER sv4 OPTIONS (table_name 'cl4'); CREATE TABLE pf0 (LIKE pl); ALTER FOREIGN TABLE ft10 INHERIT pf0; ALTER FOREIGN TABLE ft20 INHERIT pf0; ALTER FOREIGN TABLE ft30 INHERIT pf0; ALTER FOREIGN TABLE ft40 INHERIT pf0; CREATE TABLE pf1 (LIKE pl); ALTER FOREIGN TABLE ft11 INHERIT pf1; ALTER FOREIGN TABLE ft22 INHERIT pf1; ALTER FOREIGN TABLE ft33 INHERIT pf1; ALTER FOREIGN TABLE ft44 INHERIT pf1; CREATE FOREIGN TABLE ftp10 (a int, b int) SERVER sv0 OPTIONS (table_name 'cl1'); CREATE FOREIGN TABLE ftp20 (a int, b int) SERVER sv0 OPTIONS (table_name 'cl2'); CREATE FOREIGN TABLE ftp30 (a int, b int) SERVER sv0 OPTIONS (table_name 'cl3'); CREATE FOREIGN TABLE ftp40 (a int, b int) SERVER sv0 OPTIONS (table_name 'cl4'); CREATE FOREIGN TABLE ftp11 (a int, b int) SERVER sv1 OPTIONS (table_name 'cl1'); CREATE FOREIGN TABLE ftp22 (a int, b int) SERVER sv2 OPTIONS (table_name 'cl2'); CREATE FOREIGN TABLE ftp33 (a int, b int) SERVER sv3 OPTIONS (table_name 'cl3'); CREATE FOREIGN TABLE ftp44 (a int, b int) SERVER sv4 OPTIONS (table_name 'cl4'); CREATE TABLE ptf0 (a int, b int) PARTITION BY RANGE (a); ALTER TABLE ptf0 ATTACH PARTITION ftp10 FOR VALUES FROM (:th0) TO (:th1); ALTER TABLE ptf0 ATTACH PARTITION ftp20 FOR VALUES FROM (:th1) TO (:th2); ALTER TABLE ptf0 ATTACH PARTITION ftp30 FOR VALUES FROM (:th2) TO (:th3); ALTER TABLE ptf0 ATTACH PARTITION ftp40 FOR VALUES FROM (:th3) TO (:th4); CREATE TABLE ptf1 (a int, b int) PARTITION BY RANGE (a); ALTER TABLE ptf1 ATTACH PARTITION ftp11 FOR VALUES FROM (:th0) TO (:th1); ALTER TABLE ptf1 ATTACH PARTITION ftp22 FOR VALUES FROM (:th1) TO (:th2); ALTER TABLE ptf1 ATTACH PARTITION ftp33 FOR VALUES FROM (:th2) TO (:th3); ALTER TABLE ptf1 ATTACH PARTITION ftp44 FOR VALUES FROM (:th3) TO (:th4); ANALYZE; #! /bin/bash function do_test() { echo $1 for i in $(seq 1 14); do psql postgres -c "set max_parallel_workers_per_gather to 0; set log_min_duration_statement =0; set client_min_messages=log; explain analyze select sum(a) from $1"; done | grep LOG } function do_test_union1() { echo "UNION_pf0" for i in $(seq 1 14); do psql postgres -c "set max_parallel_workers_per_gather to 0; set log_min_duration_statement =0; set client_min_messages=log; SELECT sum(a) FROM (SELECT a FROM ft10 UNION ALL SELECT a FROM ft20 UNION ALL SELECT a FROMft30 UNION ALL SELECT a FROM ft40) as pf0"; done | grep LOG } function do_test_union2() { echo "UNION_pf1" for i in $(seq 1 14); do psql postgres -c "set max_parallel_workers_per_gather to 0; set log_min_duration_statement =0; set client_min_messages=log; SELECT sum(a) FROM (SELECT a FROM ft11 UNION ALL SELECT a FROM ft22 UNION ALL SELECT a FROMft33 UNION ALL SELECT a FROM ft44) as pf1"; done | grep LOG } function warmup() { for i in $(seq 1 5); do psql postgres -c "set log_min_duration_statement = -1; select sum(a) from $1"; done 1>&2 > /dev/null } #for t in "t0" "pll"; #for t in "ft0" "pf0" "pf1" "ptf0" "ptf1"; #for t in "pf0" "ptf0"; for t in "t0" "pll" "ft0" "pf0" "pf1" "ptf0" "ptf1"; do warmup $t do_test $t done exit for t in "ft0" "pf0" "pf1" "ptf0" "ptf1"; do warmup $t do_test $t done #do_test_union1 #do_test_union2
pgsql-hackers by date: