Merge pull request #4196 from citusdata/support-explain-analyze-wal

Support EXPLAIN(ANALYZE, WAL)
pull/4213/head
Ahmet Gedemenli 2020-10-01 14:43:42 +03:00 committed by GitHub
commit 6a341b6ab8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 144 additions and 17 deletions

View File

@ -83,6 +83,7 @@ typedef struct
bool verbose; bool verbose;
bool costs; bool costs;
bool buffers; bool buffers;
bool wal;
bool timing; bool timing;
bool summary; bool summary;
ExplainFormat format; ExplainFormat format;
@ -91,7 +92,7 @@ typedef struct
/* EXPLAIN flags of current distributed explain */ /* EXPLAIN flags of current distributed explain */
static ExplainOptions CurrentDistributedQueryExplainOptions = { static ExplainOptions CurrentDistributedQueryExplainOptions = {
0, 0, 0, 0, 0, EXPLAIN_FORMAT_TEXT 0, 0, 0, 0, 0, 0, EXPLAIN_FORMAT_TEXT
}; };
/* Result for a single remote EXPLAIN command */ /* Result for a single remote EXPLAIN command */
@ -904,12 +905,18 @@ BuildRemoteExplainQuery(char *queryString, ExplainState *es)
appendStringInfo(explainQuery, appendStringInfo(explainQuery,
"EXPLAIN (ANALYZE %s, VERBOSE %s, " "EXPLAIN (ANALYZE %s, VERBOSE %s, "
"COSTS %s, BUFFERS %s, TIMING %s, SUMMARY %s, " "COSTS %s, BUFFERS %s, "
"FORMAT %s) %s", #if PG_VERSION_NUM >= PG_VERSION_13
"WAL %s, "
#endif
"TIMING %s, SUMMARY %s, FORMAT %s) %s",
es->analyze ? "TRUE" : "FALSE", es->analyze ? "TRUE" : "FALSE",
es->verbose ? "TRUE" : "FALSE", es->verbose ? "TRUE" : "FALSE",
es->costs ? "TRUE" : "FALSE", es->costs ? "TRUE" : "FALSE",
es->buffers ? "TRUE" : "FALSE", es->buffers ? "TRUE" : "FALSE",
#if PG_VERSION_NUM >= PG_VERSION_13
es->wal ? "TRUE" : "FALSE",
#endif
es->timing ? "TRUE" : "FALSE", es->timing ? "TRUE" : "FALSE",
es->summary ? "TRUE" : "FALSE", es->summary ? "TRUE" : "FALSE",
formatStr, formatStr,
@ -1005,6 +1012,9 @@ worker_save_query_explain_analyze(PG_FUNCTION_ARGS)
/* use the same defaults as NewExplainState() for following options */ /* use the same defaults as NewExplainState() for following options */
es->buffers = ExtractFieldBoolean(explainOptions, "buffers", es->buffers); es->buffers = ExtractFieldBoolean(explainOptions, "buffers", es->buffers);
#if PG_VERSION_NUM >= PG_VERSION_13
es->wal = ExtractFieldBoolean(explainOptions, "wal", es->wal);
#endif
es->costs = ExtractFieldBoolean(explainOptions, "costs", es->costs); es->costs = ExtractFieldBoolean(explainOptions, "costs", es->costs);
es->summary = ExtractFieldBoolean(explainOptions, "summary", es->summary); es->summary = ExtractFieldBoolean(explainOptions, "summary", es->summary);
es->verbose = ExtractFieldBoolean(explainOptions, "verbose", es->verbose); es->verbose = ExtractFieldBoolean(explainOptions, "verbose", es->verbose);
@ -1206,6 +1216,9 @@ CitusExplainOneQuery(Query *query, int cursorOptions, IntoClause *into,
/* save the flags of current EXPLAIN command */ /* save the flags of current EXPLAIN command */
CurrentDistributedQueryExplainOptions.costs = es->costs; CurrentDistributedQueryExplainOptions.costs = es->costs;
CurrentDistributedQueryExplainOptions.buffers = es->buffers; CurrentDistributedQueryExplainOptions.buffers = es->buffers;
#if PG_VERSION_NUM >= PG_VERSION_13
CurrentDistributedQueryExplainOptions.wal = es->wal;
#endif
CurrentDistributedQueryExplainOptions.verbose = es->verbose; CurrentDistributedQueryExplainOptions.verbose = es->verbose;
CurrentDistributedQueryExplainOptions.summary = es->summary; CurrentDistributedQueryExplainOptions.summary = es->summary;
CurrentDistributedQueryExplainOptions.timing = es->timing; CurrentDistributedQueryExplainOptions.timing = es->timing;
@ -1482,11 +1495,18 @@ WrapQueryForExplainAnalyze(const char *queryString, TupleDesc tupleDesc)
} }
StringInfo explainOptions = makeStringInfo(); StringInfo explainOptions = makeStringInfo();
appendStringInfo(explainOptions, "{\"verbose\": %s, \"costs\": %s, \"buffers\": %s, " appendStringInfo(explainOptions,
"\"timing\": %s, \"summary\": %s, \"format\": \"%s\"}", "{\"verbose\": %s, \"costs\": %s, \"buffers\": %s, "
#if PG_VERSION_NUM >= PG_VERSION_13
"\"wal\": %s, "
#endif
"\"timing\": %s, \"summary\": %s, \"format\": \"%s\"}",
CurrentDistributedQueryExplainOptions.verbose ? "true" : "false", CurrentDistributedQueryExplainOptions.verbose ? "true" : "false",
CurrentDistributedQueryExplainOptions.costs ? "true" : "false", CurrentDistributedQueryExplainOptions.costs ? "true" : "false",
CurrentDistributedQueryExplainOptions.buffers ? "true" : "false", CurrentDistributedQueryExplainOptions.buffers ? "true" : "false",
#if PG_VERSION_NUM >= PG_VERSION_13
CurrentDistributedQueryExplainOptions.wal ? "true" : "false",
#endif
CurrentDistributedQueryExplainOptions.timing ? "true" : "false", CurrentDistributedQueryExplainOptions.timing ? "true" : "false",
CurrentDistributedQueryExplainOptions.summary ? "true" : "false", CurrentDistributedQueryExplainOptions.summary ? "true" : "false",
ExplainFormatStr(CurrentDistributedQueryExplainOptions.format)); ExplainFormatStr(CurrentDistributedQueryExplainOptions.format));
@ -1632,7 +1652,10 @@ ExplainWorkerPlan(PlannedStmt *plannedstmt, DestReceiver *dest, ExplainState *es
if (es->buffers) if (es->buffers)
instrument_option |= INSTRUMENT_BUFFERS; instrument_option |= INSTRUMENT_BUFFERS;
#if PG_VERSION_NUM >= PG_VERSION_13
if (es->wal)
instrument_option |= INSTRUMENT_WAL;
#endif
/* /*
* We always collect timing for the entire statement, even when node-level * We always collect timing for the entire statement, even when node-level
* timing is off, so we don't look at es->timing here. (We could skip * timing is off, so we don't look at es->timing here. (We could skip

View File

@ -170,15 +170,97 @@ SELECT create_distributed_table('test_table', 'a');
-- we currently don't support this -- we currently don't support this
CREATE INDEX test_table_index ON test_table USING gist (b tsvector_ops(siglen = 100)); CREATE INDEX test_table_index ON test_table USING gist (b tsvector_ops(siglen = 100));
ERROR: citus currently doesn't support operator class parameters in indexes ERROR: citus currently doesn't support operator class parameters in indexes
-- testing WAL
CREATE TABLE test_wal(a int, b int);
-- test WAL without ANALYZE, this should raise an error
EXPLAIN (WAL) INSERT INTO test_wal VALUES(1,11);
ERROR: EXPLAIN option WAL requires ANALYZE
-- test WAL working properly for router queries
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
INSERT INTO test_wal VALUES(1,11);
QUERY PLAN
---------------------------------------------------------------------
Insert on test_wal (actual rows=0 loops=1)
WAL: records=1 bytes=63
-> Result (actual rows=1 loops=1)
(3 rows)
SELECT create_distributed_table('test_wal', 'a');
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$test_pg13.test_wal$$)
create_distributed_table
---------------------------------------------------------------------
(1 row)
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
INSERT INTO test_wal VALUES(2,22);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive) (actual rows=0 loops=1)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Insert on test_wal_65013 (actual rows=0 loops=1)
WAL: records=1 bytes=63
-> Result (actual rows=1 loops=1)
(8 rows)
-- Test WAL working for multi-shard query
SET citus.explain_all_tasks TO on;
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
INSERT INTO test_wal VALUES(3,33),(4,44),(5,55) RETURNING *;
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive) (actual rows=3 loops=1)
Task Count: 1
Tuple data received from nodes: 9 bytes
Tasks Shown: All
-> Task
Tuple data received from node: 9 bytes
Node: host=localhost port=xxxxx dbname=regression
-> Insert on test_wal_65012 citus_table_alias (actual rows=3 loops=1)
WAL: records=3 bytes=189
-> Values Scan on "*VALUES*" (actual rows=3 loops=1)
(10 rows)
-- make sure WAL works in distributed subplans
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
WITH cte_1 AS (INSERT INTO test_wal VALUES(6,66),(7,77),(8,88) RETURNING *)
SELECT * FROM cte_1;
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive) (actual rows=3 loops=1)
-> Distributed Subplan XXX_1
Intermediate Data Size: 54 bytes
Result destination: Write locally
-> Custom Scan (Citus Adaptive) (actual rows=3 loops=1)
Task Count: 2
Tuple data received from nodes: 9 bytes
Tasks Shown: All
-> Task
Tuple data received from node: 6 bytes
Node: host=localhost port=xxxxx dbname=regression
-> Insert on test_wal_65012 citus_table_alias (actual rows=2 loops=1)
WAL: records=2 bytes=126
-> Values Scan on "*VALUES*" (actual rows=2 loops=1)
-> Task
Tuple data received from node: 3 bytes
Node: host=localhost port=xxxxx dbname=regression
-> Insert on test_wal_65013 citus_table_alias (actual rows=1 loops=1)
WAL: records=1 bytes=63
-> Result (actual rows=1 loops=1)
Task Count: 1
Tuple data received from nodes: 9 bytes
Tasks Shown: All
-> Task
Tuple data received from node: 9 bytes
Node: host=localhost port=xxxxx dbname=regression
-> Function Scan on read_intermediate_result intermediate_result (actual rows=3 loops=1)
(27 rows)
SET client_min_messages TO WARNING;
drop schema test_pg13 cascade; drop schema test_pg13 cascade;
NOTICE: drop cascades to 10 other objects
DETAIL: drop cascades to table dist_table
drop cascades to table generated_col_table
drop cascades to view v
drop cascades to table ab
drop cascades to table text_table
drop cascades to function myvarcharout(myvarchar)
drop cascades to type myvarchar
drop cascades to function myvarcharin(cstring,oid,integer)
drop cascades to table my_table
drop cascades to table test_table

View File

@ -94,4 +94,26 @@ SELECT create_distributed_table('test_table', 'a');
-- we currently don't support this -- we currently don't support this
CREATE INDEX test_table_index ON test_table USING gist (b tsvector_ops(siglen = 100)); CREATE INDEX test_table_index ON test_table USING gist (b tsvector_ops(siglen = 100));
-- testing WAL
CREATE TABLE test_wal(a int, b int);
-- test WAL without ANALYZE, this should raise an error
EXPLAIN (WAL) INSERT INTO test_wal VALUES(1,11);
-- test WAL working properly for router queries
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
INSERT INTO test_wal VALUES(1,11);
SELECT create_distributed_table('test_wal', 'a');
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
INSERT INTO test_wal VALUES(2,22);
-- Test WAL working for multi-shard query
SET citus.explain_all_tasks TO on;
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
INSERT INTO test_wal VALUES(3,33),(4,44),(5,55) RETURNING *;
-- make sure WAL works in distributed subplans
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
WITH cte_1 AS (INSERT INTO test_wal VALUES(6,66),(7,77),(8,88) RETURNING *)
SELECT * FROM cte_1;
SET client_min_messages TO WARNING;
drop schema test_pg13 cascade; drop schema test_pg13 cascade;