From 9dcc7b38bc5ff8352268742f00f5fabd95d55a0f Mon Sep 17 00:00:00 2001 From: "Andrei V. Lepikhov" Date: Tue, 18 Mar 2025 10:40:22 +0100 Subject: [PATCH 1/3] Code (extension and the core) changes needed to be used with the explain extension --- aqo.h | 5 ++--- aqo_master.patch | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/aqo.h b/aqo.h index 8f61f4a..fe7f90d 100644 --- a/aqo.h +++ b/aqo.h @@ -144,7 +144,6 @@ #include "utils/snapmgr.h" #include "machine_learning.h" -//#include "storage.h" /* Check PostgreSQL version (9.6.0 contains important changes in planner) */ #if PG_VERSION_NUM < 90600 @@ -271,11 +270,11 @@ extern bool update_fss_ext(uint64 fs, int fss, OkNNrdata *data, List *reloids); /* Query preprocessing hooks */ extern void print_into_explain(PlannedStmt *plannedstmt, IntoClause *into, - ExplainState *es, const char *queryString, + struct ExplainState *es, const char *queryString, ParamListInfo params, const instr_time *planduration, QueryEnvironment *queryEnv); -extern void print_node_explain(ExplainState *es, PlanState *ps, Plan *plan); +extern void print_node_explain(struct ExplainState *es, PlanState *ps, Plan *plan); /* Cardinality estimation */ extern double predict_for_relation(List *restrict_clauses, List *selectivities, diff --git a/aqo_master.patch b/aqo_master.patch index e7120c7..dd87274 100644 --- a/aqo_master.patch +++ b/aqo_master.patch @@ -1,8 +1,8 @@ diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c -index 19ffcc2cacb..93934d42e30 100644 +index 22616cf7add..8a28b783f72 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c -@@ -27,6 +27,7 @@ +@@ -29,6 +29,7 @@ #include "nodes/extensible.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" @@ -10,9 +10,9 @@ index 19ffcc2cacb..93934d42e30 100644 #include "parser/analyze.h" #include "parser/parsetree.h" #include "rewrite/rewriteHandler.h" -@@ -50,6 +51,12 @@ ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL; - /* Hook for plugins to get control in explain_get_index_name() */ - explain_get_index_name_hook_type explain_get_index_name_hook = NULL; +@@ -45,6 +46,12 @@ + #include "utils/typcache.h" + #include "utils/xml.h" +/* Hook for plugins to get control in ExplainOnePlan() */ +ExplainOnePlan_hook_type ExplainOnePlan_hook = NULL; @@ -21,9 +21,9 @@ index 19ffcc2cacb..93934d42e30 100644 +ExplainOneNode_hook_type ExplainOneNode_hook = NULL; + - /* - * Various places within need to convert bytes to kilobytes. Round these up -@@ -815,6 +822,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, CachedPlan *cplan, + /* Hook for plugins to get control in ExplainOneQuery() */ + ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL; +@@ -690,6 +697,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, CachedPlan *cplan, ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3, es); @@ -34,7 +34,7 @@ index 19ffcc2cacb..93934d42e30 100644 ExplainCloseGroup("Query", NULL, true, es); } -@@ -2009,6 +2020,9 @@ ExplainNode(PlanState *planstate, List *ancestors, +@@ -1884,6 +1895,9 @@ ExplainNode(PlanState *planstate, List *ancestors, } } @@ -521,22 +521,22 @@ index 5b35debc8ff..06a7bebe4f8 100644 * estimate_num_groups - Estimate number of groups in a grouped query * diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h -index 64547bd9b9c..74792f1a8cf 100644 +index e8e92f966a1..323b3391b35 100644 --- a/src/include/commands/explain.h +++ b/src/include/commands/explain.h -@@ -87,6 +87,18 @@ extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook; +@@ -49,6 +49,18 @@ extern PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook; typedef const char *(*explain_get_index_name_hook_type) (Oid indexId); extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook; +/* Hook for plugins to get control in ExplainOnePlan() */ +typedef void (*ExplainOnePlan_hook_type) (PlannedStmt *plannedstmt, IntoClause *into, -+ ExplainState *es, const char *queryString, ++ struct ExplainState *es, const char *queryString, + ParamListInfo params, const instr_time *planduration, + QueryEnvironment *queryEnv); +extern PGDLLIMPORT ExplainOnePlan_hook_type ExplainOnePlan_hook; + +/* Explain a node info */ -+typedef void (*ExplainOneNode_hook_type) (ExplainState *es, ++typedef void (*ExplainOneNode_hook_type) (struct ExplainState *es, + PlanState *ps, + Plan *plan); +extern PGDLLIMPORT ExplainOneNode_hook_type ExplainOneNode_hook; From 7d076843e7a0e558cf708690100d0d9ed4c1e147 Mon Sep 17 00:00:00 2001 From: "Andrei V. Lepikhov" Date: Tue, 18 Mar 2025 12:42:03 +0100 Subject: [PATCH 2/3] Changes needed to use core hooks proposed. --- aqo.c | 12 ++-- aqo.h | 15 ++-- expected/aqo_fdw.out | 34 ++++----- expected/feature_subspace.out | 4 +- expected/gucs.out | 4 +- expected/look_a_like.out | 132 +++++++++++++++++----------------- expected/parallel_workers.out | 18 ++--- expected/unsupported.out | 80 ++++++++++----------- postprocessing.c | 63 ++++++++++------ 9 files changed, 191 insertions(+), 171 deletions(-) diff --git a/aqo.c b/aqo.c index a5d4ff5..022f406 100644 --- a/aqo.c +++ b/aqo.c @@ -115,8 +115,8 @@ set_baserel_rows_estimate_hook_type prev_set_baserel_rows_estimate_hook; get_parameterized_baserel_size_hook_type prev_get_parameterized_baserel_size_hook; set_joinrel_size_estimates_hook_type prev_set_joinrel_size_estimates_hook; get_parameterized_joinrel_size_hook_type prev_get_parameterized_joinrel_size_hook; -ExplainOnePlan_hook_type prev_ExplainOnePlan_hook; -ExplainOneNode_hook_type prev_ExplainOneNode_hook; +explain_per_plan_hook_type prev_explain_per_plan_hook = NULL; +explain_per_node_hook_type prev_explain_per_node_hook = NULL; static shmem_request_hook_type prev_shmem_request_hook = NULL; static object_access_hook_type prev_object_access_hook; @@ -480,10 +480,10 @@ _PG_init(void) create_plan_hook = aqo_create_plan_hook; /* Service hooks. */ - prev_ExplainOnePlan_hook = ExplainOnePlan_hook; - ExplainOnePlan_hook = print_into_explain; - prev_ExplainOneNode_hook = ExplainOneNode_hook; - ExplainOneNode_hook = print_node_explain; + prev_explain_per_plan_hook = explain_per_plan_hook; + explain_per_plan_hook = print_into_explain; + prev_explain_per_node_hook = explain_per_node_hook; + explain_per_node_hook = print_node_explain; prev_create_upper_paths_hook = create_upper_paths_hook; create_upper_paths_hook = aqo_store_upper_signature_hook; diff --git a/aqo.h b/aqo.h index fe7f90d..1678969 100644 --- a/aqo.h +++ b/aqo.h @@ -252,8 +252,8 @@ extern set_joinrel_size_estimates_hook_type prev_set_joinrel_size_estimates_hook; extern get_parameterized_joinrel_size_hook_type prev_get_parameterized_joinrel_size_hook; -extern ExplainOnePlan_hook_type prev_ExplainOnePlan_hook; -extern ExplainOneNode_hook_type prev_ExplainOneNode_hook; +extern explain_per_plan_hook_type prev_explain_per_plan_hook; +extern explain_per_node_hook_type prev_explain_per_node_hook; extern void ppi_hook(ParamPathInfo *ppi); extern int aqo_statement_timeout; @@ -269,12 +269,15 @@ extern bool load_fss_ext(uint64 fs, int fss, OkNNrdata *data, List **reloids); extern bool update_fss_ext(uint64 fs, int fss, OkNNrdata *data, List *reloids); /* Query preprocessing hooks */ -extern void print_into_explain(PlannedStmt *plannedstmt, IntoClause *into, - struct ExplainState *es, const char *queryString, +extern void print_into_explain(PlannedStmt *ps, + IntoClause *into, + struct ExplainState *es, + const char *queryString, ParamListInfo params, - const instr_time *planduration, QueryEnvironment *queryEnv); -extern void print_node_explain(struct ExplainState *es, PlanState *ps, Plan *plan); +extern void print_node_explain(PlanState *ps, List *ancestors, + const char *relationship, const char *plan_name, + struct ExplainState *es); /* Cardinality estimation */ extern double predict_for_relation(List *restrict_clauses, List *selectivities, diff --git a/expected/aqo_fdw.out b/expected/aqo_fdw.out index 123f9a3..2ff7a44 100644 --- a/expected/aqo_fdw.out +++ b/expected/aqo_fdw.out @@ -66,9 +66,9 @@ SELECT str FROM expln(' str ----------------------------------------------------------- Foreign Scan on public.frgn (actual rows=1.00 loops=1) - AQO not used Output: x Remote SQL: SELECT x FROM public.local WHERE ((x < 10)) + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -81,9 +81,9 @@ SELECT str FROM expln(' str ----------------------------------------------------------- Foreign Scan on public.frgn (actual rows=1.00 loops=1) - AQO: rows=1, error=0% Output: x Remote SQL: SELECT x FROM public.local WHERE ((x < 10)) + AQO: rows=1, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -108,8 +108,8 @@ SELECT str FROM expln(' str --------------------------------------------------------------- Merge Join (actual rows=1.00 loops=1) - AQO not used Merge Cond: (a.x = b.x) + AQO not used -> Sort (actual rows=1.00 loops=1) Sort Key: a.x -> Foreign Scan on frgn a (actual rows=1.00 loops=1) @@ -131,10 +131,10 @@ SELECT str FROM expln(' str -------------------------------------------------------------------------------------------------------- Foreign Scan (actual rows=1.00 loops=1) - AQO: rows=1, error=0% Output: a.x, b.x Relations: (public.frgn a) INNER JOIN (public.frgn b) Remote SQL: SELECT r1.x, r2.x FROM (public.local r1 INNER JOIN public.local r2 ON (((r1.x = r2.x)))) + AQO: rows=1, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -153,8 +153,8 @@ WHERE a.aid = b.aid AND b.bval like 'val%'; QUERY PLAN ----------------------------------------------- Foreign Scan (actual rows=1000.00 loops=1) - AQO not used Relations: (frgn_a a) INNER JOIN (frgn_b b) + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -166,8 +166,8 @@ WHERE a.aid = b.aid AND b.bval like 'val%'; QUERY PLAN ----------------------------------------------- Foreign Scan (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Relations: (frgn_a a) INNER JOIN (frgn_b b) + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -207,17 +207,17 @@ WHERE str NOT LIKE '%Memory%'; Append (actual rows=1000.00 loops=1) AQO not used -> Foreign Scan (actual rows=400.00 loops=1) - AQO not used Relations: (main_p0 a_1) INNER JOIN (ref_p0 b_1) - -> Foreign Scan (actual rows=300.00 loops=1) AQO not used + -> Foreign Scan (actual rows=300.00 loops=1) Relations: (main_p1 a_2) INNER JOIN (ref_p1 b_2) - -> Hash Join (actual rows=300.00 loops=1) AQO not used + -> Hash Join (actual rows=300.00 loops=1) Hash Cond: (b_3.aid = a_3.aid) + AQO not used -> Seq Scan on ref_p2 b_3 (actual rows=300.00 loops=1) - AQO not used Filter: (bval ~~ 'val%'::text) + AQO not used -> Hash (actual rows=38.00 loops=1) -> Seq Scan on main_p2 a_3 (actual rows=38.00 loops=1) AQO not used @@ -237,17 +237,17 @@ WHERE str NOT LIKE '%Memory%'; Append (actual rows=1000.00 loops=1) AQO not used -> Foreign Scan (actual rows=400.00 loops=1) - AQO: rows=400, error=0% Relations: (main_p0 a_1) INNER JOIN (ref_p0 b_1) + AQO: rows=400, error=0% -> Foreign Scan (actual rows=300.00 loops=1) - AQO: rows=300, error=0% Relations: (main_p1 a_2) INNER JOIN (ref_p1 b_2) - -> Hash Join (actual rows=300.00 loops=1) AQO: rows=300, error=0% + -> Hash Join (actual rows=300.00 loops=1) Hash Cond: (b_3.aid = a_3.aid) + AQO: rows=300, error=0% -> Seq Scan on ref_p2 b_3 (actual rows=300.00 loops=1) - AQO: rows=300, error=0% Filter: (bval ~~ 'val%'::text) + AQO: rows=300, error=0% -> Hash (actual rows=38.00 loops=1) -> Seq Scan on main_p2 a_3 (actual rows=38.00 loops=1) AQO: rows=38, error=0% @@ -266,14 +266,14 @@ SELECT * FROM frgn AS a, frgn AS b WHERE a.x Foreign Scan on frgn a (actual rows=1.00 loops=1) AQO not used -> Materialize (actual rows=1.00 loops=1) - AQO not used Storage: Memory Maximum Storage: 17kB + AQO not used -> Foreign Scan on frgn b (actual rows=1.00 loops=1) AQO not used Using aqo: true @@ -288,10 +288,10 @@ SELECT str FROM expln(' str -------------------------------------------------------------------------------------------------------- Foreign Scan (actual rows=0.00 loops=1) - AQO: rows=1, error=100% Output: a.x, b.x Relations: (public.frgn a) INNER JOIN (public.frgn b) Remote SQL: SELECT r1.x, r2.x FROM (public.local r1 INNER JOIN public.local r2 ON (((r1.x < r2.x)))) + AQO: rows=1, error=100% Using aqo: true AQO mode: LEARN JOINS: 0 diff --git a/expected/feature_subspace.out b/expected/feature_subspace.out index 75ea3fb..3ef12af 100644 --- a/expected/feature_subspace.out +++ b/expected/feature_subspace.out @@ -31,8 +31,8 @@ WHERE str NOT LIKE '%Memory%'; result -------------------------------------------------------- Merge Left Join (actual rows=10.00 loops=1) - AQO not used Merge Cond: (a.x = b.x) + AQO not used -> Sort (actual rows=10.00 loops=1) Sort Key: a.x -> Seq Scan on a (actual rows=10.00 loops=1) @@ -54,8 +54,8 @@ WHERE str NOT LIKE '%Memory%'; result -------------------------------------------------------- Merge Left Join (actual rows=100.00 loops=1) - AQO not used Merge Cond: (b.x = a.x) + AQO not used -> Sort (actual rows=100.00 loops=1) Sort Key: b.x -> Seq Scan on b (actual rows=100.00 loops=1) diff --git a/expected/gucs.out b/expected/gucs.out index 2ec19cb..3680c5a 100644 --- a/expected/gucs.out +++ b/expected/gucs.out @@ -35,8 +35,8 @@ SELECT regexp_replace( str --------------------------------------------------- Seq Scan on public.t (actual rows=100.00 loops=1) - AQO not used Output: x + AQO not used Query Identifier: N Using aqo: true AQO mode: LEARN @@ -51,8 +51,8 @@ SELECT regexp_replace( str --------------------------------------------------- Seq Scan on public.t (actual rows=100.00 loops=1) - AQO: rows=100, error=0% Output: x + AQO: rows=100, error=0% Query Identifier: N Using aqo: true AQO mode: LEARN diff --git a/expected/look_a_like.out b/expected/look_a_like.out index a252524..79255d4 100644 --- a/expected/look_a_like.out +++ b/expected/look_a_like.out @@ -42,19 +42,19 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ----------------------------------------------------------- Nested Loop (actual rows=10000.00 loops=1) - AQO not used Disabled: true Output: a.x1, b.y1 + AQO not used -> Seq Scan on public.a (actual rows=100.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3 Filter: ((a.x1 = 5) AND (a.x2 = 5)) Rows Removed by Filter: 900 - -> Seq Scan on public.b (actual rows=100.00 loops=100) AQO not used + -> Seq Scan on public.b (actual rows=100.00 loops=100) Output: b.y1, b.y2, b.y3 Filter: (b.y1 = 5) Rows Removed by Filter: 900 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -67,19 +67,19 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ----------------------------------------------------------- Nested Loop Left Join (actual rows=10000.00 loops=1) - AQO not used Disabled: true Output: a.x1, b.y1 + AQO not used -> Seq Scan on public.a (actual rows=100.00 loops=1) - AQO: rows=100, error=0% Output: a.x1, a.x2, a.x3 Filter: ((a.x1 = 5) AND (a.x2 = 5)) Rows Removed by Filter: 900 - -> Seq Scan on public.b (actual rows=100.00 loops=100) AQO: rows=100, error=0% + -> Seq Scan on public.b (actual rows=100.00 loops=100) Output: b.y1, b.y2, b.y3 Filter: (b.y1 = 5) Rows Removed by Filter: 900 + AQO: rows=100, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -92,19 +92,19 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result --------------------------------------------------------------- Hash Join (actual rows=50000.00 loops=1) - AQO not used Output: a.x1, b.y1 Hash Cond: (b.y1 = a.x1) + AQO not used -> Seq Scan on public.b (actual rows=1000.00 loops=1) - AQO not used Output: b.y1, b.y2, b.y3 + AQO not used -> Hash (actual rows=500.00 loops=1) Output: a.x1 -> Seq Scan on public.a (actual rows=500.00 loops=1) - AQO not used Output: a.x1 Filter: ((a.x1 < 5) AND (a.x2 < 5)) Rows Removed by Filter: 500 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -118,19 +118,19 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result --------------------------------------------------------------- Hash Join (actual rows=50000.00 loops=1) - AQO: rows=50000, error=0% Output: a.x1, b.y1 Hash Cond: (b.y1 = a.x1) + AQO: rows=50000, error=0% -> Seq Scan on public.b (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% -> Hash (actual rows=500.00 loops=1) Output: a.x1 -> Seq Scan on public.a (actual rows=500.00 loops=1) - AQO: rows=500, error=0% Output: a.x1 Filter: ((a.x1 < 10) AND (a.x2 < 5)) Rows Removed by Filter: 500 + AQO: rows=500, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -143,19 +143,19 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result --------------------------------------------------------------- Hash Join (actual rows=70000.00 loops=1) - AQO not used Output: a.x1, b.y1 Hash Cond: (b.y1 = a.x1) + AQO not used -> Seq Scan on public.b (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% -> Hash (actual rows=700.00 loops=1) Output: a.x1 -> Seq Scan on public.a (actual rows=700.00 loops=1) - AQO not used Output: a.x1 Filter: ((a.x1 > 2) AND (a.x2 > 2)) Rows Removed by Filter: 300 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -168,19 +168,19 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------- Hash Join (actual rows=40000.00 loops=1) - AQO not used Output: a.x1, b.y1 Hash Cond: (b.y1 = a.x1) + AQO not used -> Seq Scan on public.b (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% -> Hash (actual rows=400.00 loops=1) Output: a.x1 -> Seq Scan on public.a (actual rows=400.00 loops=1) - AQO not used Output: a.x1 Filter: ((a.x1 > 5) AND (a.x2 > 5) AND (a.x3 < 10)) Rows Removed by Filter: 600 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -193,19 +193,19 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------- Hash Join (actual rows=50000.00 loops=1) - AQO not used Output: a.x1, b.y1 Hash Cond: (b.y1 = a.x1) + AQO not used -> Seq Scan on public.b (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% -> Hash (actual rows=500.00 loops=1) Output: a.x1 -> Seq Scan on public.a (actual rows=500.00 loops=1) - AQO not used Output: a.x1 Filter: ((a.x1 < 5) AND (a.x2 < 5) AND (a.x3 < 10)) Rows Removed by Filter: 500 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -219,19 +219,19 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ Hash Join (actual rows=40000.00 loops=1) - AQO: rows=50000, error=20% Output: a.x1, b.y1 Hash Cond: (b.y1 = a.x1) + AQO: rows=50000, error=20% -> Seq Scan on public.b (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% -> Hash (actual rows=400.00 loops=1) Output: a.x1 -> Seq Scan on public.a (actual rows=400.00 loops=1) - AQO: rows=500, error=20% Output: a.x1 Filter: ((a.x1 < 5) AND (a.x2 < 4) AND (a.x3 < 5)) Rows Removed by Filter: 600 + AQO: rows=500, error=20% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -244,21 +244,21 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ HashAggregate (actual rows=2.00 loops=1) - AQO not used Output: a.x1 Group Key: a.x1 + AQO not used -> Nested Loop (actual rows=200000.00 loops=1) - AQO not used Disabled: true Output: a.x1 + AQO not used -> Seq Scan on public.a (actual rows=200.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3 Filter: ((a.x1 < 4) AND (a.x3 > 1)) Rows Removed by Filter: 800 + AQO not used -> Seq Scan on public.b (actual rows=1000.00 loops=200) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 @@ -272,21 +272,21 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ HashAggregate (actual rows=2.00 loops=1) - AQO: rows=2, error=0% Output: a.x1 Group Key: a.x1 + AQO: rows=2, error=0% -> Nested Loop (actual rows=200000.00 loops=1) - AQO: rows=200000, error=0% Disabled: true Output: a.x1 + AQO: rows=200000, error=0% -> Seq Scan on public.a (actual rows=200.00 loops=1) - AQO: rows=200, error=0% Output: a.x1, a.x2, a.x3 Filter: ((a.x1 < 4) AND (a.x3 > 1)) Rows Removed by Filter: 800 + AQO: rows=200, error=0% -> Seq Scan on public.b (actual rows=1000.00 loops=200) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 @@ -299,21 +299,21 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ HashAggregate (actual rows=1.00 loops=1) - AQO: rows=2, error=50% Output: a.x1 Group Key: a.x1 + AQO: rows=2, error=50% -> Nested Loop (actual rows=100000.00 loops=1) - AQO: rows=200000, error=50% Disabled: true Output: a.x1 + AQO: rows=200000, error=50% -> Seq Scan on public.a (actual rows=100.00 loops=1) - AQO: rows=200, error=50% Output: a.x1, a.x2, a.x3 Filter: ((a.x1 < 4) AND (a.x3 > 2)) Rows Removed by Filter: 900 + AQO: rows=200, error=50% -> Seq Scan on public.b (actual rows=1000.00 loops=100) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 @@ -326,21 +326,21 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ HashAggregate (actual rows=1.00 loops=1) - AQO not used Output: a.x1 Group Key: a.x1 + AQO not used -> Nested Loop (actual rows=100000.00 loops=1) - AQO not used Disabled: true Output: a.x1 + AQO not used -> Seq Scan on public.a (actual rows=100.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3 Filter: ((a.x1 < 3) AND (a.x2 < 5) AND (a.x3 > 1)) Rows Removed by Filter: 900 + AQO not used -> Seq Scan on public.b (actual rows=1000.00 loops=100) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 @@ -353,21 +353,21 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ HashAggregate (actual rows=2.00 loops=1) - AQO not used Output: a.x1 Group Key: a.x1 + AQO not used -> Nested Loop (actual rows=200000.00 loops=1) - AQO not used Disabled: true Output: a.x1 + AQO not used -> Seq Scan on public.a (actual rows=200.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3 Filter: ((a.x1 > 1) AND (a.x2 < 4) AND (a.x3 > 1)) Rows Removed by Filter: 800 + AQO not used -> Seq Scan on public.b (actual rows=1000.00 loops=200) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 @@ -380,21 +380,21 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ HashAggregate (actual rows=2.00 loops=1) - AQO not used Output: a.x1 Group Key: a.x1 + AQO not used -> Nested Loop (actual rows=200000.00 loops=1) - AQO not used Disabled: true Output: a.x1 + AQO not used -> Seq Scan on public.a (actual rows=200.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3 Filter: ((a.x1 > 1) AND (a.x2 < 4) AND (a.x3 < 5)) Rows Removed by Filter: 800 + AQO not used -> Seq Scan on public.b (actual rows=1000.00 loops=200) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 @@ -407,23 +407,23 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ HashAggregate (actual rows=2.00 loops=1) - AQO not used Output: a.x1 Group Key: a.x1 + AQO not used -> Nested Loop (actual rows=140000.00 loops=1) - AQO not used Disabled: true Output: a.x1 + AQO not used -> Seq Scan on public.a (actual rows=200.00 loops=1) - AQO: rows=100, error=-100% Output: a.x1, a.x2, a.x3 Filter: ((a.x1 < 4) AND (a.x2 < 5) AND (a.x3 > 1)) Rows Removed by Filter: 800 + AQO: rows=100, error=-100% -> Seq Scan on public.b (actual rows=700.00 loops=200) - AQO not used Output: b.y1, b.y2, b.y3 Filter: (b.y1 > 2) Rows Removed by Filter: 300 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 1 @@ -437,23 +437,23 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ------------------------------------------------------------------ HashAggregate (actual rows=1.00 loops=1) - AQO: rows=2, error=50% Output: a.x1 Group Key: a.x1 + AQO: rows=2, error=50% -> Nested Loop (actual rows=70000.00 loops=1) - AQO: rows=140000, error=50% Disabled: true Output: a.x1 + AQO: rows=140000, error=50% -> Seq Scan on public.a (actual rows=100.00 loops=1) - AQO: rows=200, error=50% Output: a.x1, a.x2, a.x3 Filter: ((a.x1 < 3) AND (a.x2 < 4) AND (a.x3 > 1)) Rows Removed by Filter: 900 + AQO: rows=200, error=50% -> Seq Scan on public.b (actual rows=700.00 loops=100) - AQO: rows=700, error=0% Output: b.y1, b.y2, b.y3 Filter: (b.y1 > 2) Rows Removed by Filter: 300 + AQO: rows=700, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 @@ -469,26 +469,26 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ---------------------------------------------------------------------- Hash Left Join (actual rows=0.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3, b.y1, b.y2, b.y3 Hash Cond: (a.x1 = b.y1) + AQO not used -> Hash Anti Join (actual rows=0.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3 Hash Cond: (a.x1 = c.z1) + AQO not used -> Seq Scan on public.a (actual rows=1000.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3 + AQO not used -> Hash (actual rows=1000.00 loops=1) Output: c.z1 -> Seq Scan on public.c (actual rows=1000.00 loops=1) - AQO not used Output: c.z1 + AQO not used -> Hash (never executed) Output: b.y1, b.y2, b.y3 -> Seq Scan on public.b (never executed) - AQO: rows=1000 Output: b.y1, b.y2, b.y3 + AQO: rows=1000 Using aqo: true AQO mode: LEARN JOINS: 1 @@ -501,26 +501,26 @@ WHERE str NOT LIKE 'Query Identifier%' and str NOT LIKE '%Memory%' and str NOT L result ---------------------------------------------------------------------- Hash Left Join (actual rows=10000000.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3, b.y1, b.y2, b.y3, c.z1, c.z2, c.z3 Hash Cond: (a.x1 = c.z1) + AQO not used -> Hash Left Join (actual rows=100000.00 loops=1) - AQO not used Output: a.x1, a.x2, a.x3, b.y1, b.y2, b.y3 Hash Cond: (a.x1 = b.y1) + AQO not used -> Seq Scan on public.a (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Output: a.x1, a.x2, a.x3 + AQO: rows=1000, error=0% -> Hash (actual rows=1000.00 loops=1) Output: b.y1, b.y2, b.y3 -> Seq Scan on public.b (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Output: b.y1, b.y2, b.y3 + AQO: rows=1000, error=0% -> Hash (actual rows=1000.00 loops=1) Output: c.z1, c.z2, c.z3 -> Seq Scan on public.c (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Output: c.z1, c.z2, c.z3 + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 diff --git a/expected/parallel_workers.out b/expected/parallel_workers.out index 6f4e8d3..347cc9e 100644 --- a/expected/parallel_workers.out +++ b/expected/parallel_workers.out @@ -47,9 +47,9 @@ WHERE str NOT LIKE '%Worker%'; -> Partial Aggregate (actual rows=1.00 loops=3) AQO not used -> Parallel Seq Scan on t (actual rows=333.33 loops=3) - AQO: rows=1000, error=0% Filter: ((id % '100'::numeric) = '0'::numeric) Rows Removed by Filter: 33000 + AQO: rows=1000, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -81,37 +81,37 @@ WHERE str NOT LIKE '%Workers%' AND str NOT LIKE '%Sort Method%' Aggregate (actual rows=1.00 loops=1) AQO not used -> Merge Join (actual rows=0.00 loops=1) - AQO not used Merge Cond: (t.id = q2.id) + AQO not used -> Group (actual rows=1000.00 loops=1) - AQO not used Group Key: t.id + AQO not used AQO: rows=914, error=-9% -> Sort (actual rows=333.33 loops=3) - AQO: rows=914, error=64% Sort Key: t.id + AQO: rows=914, error=64% -> Parallel Seq Scan on t (actual rows=333.33 loops=3) - AQO: rows=914, error=-9% Filter: ((id % '100'::numeric) = '0'::numeric) Rows Removed by Filter: 33000 + AQO: rows=914, error=-9% -> Sort (actual rows=1.00 loops=1) Sort Key: q2.id -> Subquery Scan on q2 (actual rows=1.00 loops=1) AQO not used -> Finalize GroupAggregate (actual rows=1.00 loops=1) - AQO not used Group Key: t_1.payload + AQO not used AQO not used -> Partial GroupAggregate (actual rows=1.00 loops=3) - AQO not used Group Key: t_1.payload + AQO not used -> Sort (actual rows=330.00 loops=3) - AQO not used Sort Key: t_1.payload + AQO not used -> Parallel Seq Scan on t t_1 (actual rows=330.00 loops=3) - AQO: rows=914, error=-8% Filter: ((id % '101'::numeric) = '0'::numeric) Rows Removed by Filter: 33003 + AQO: rows=914, error=-8% Using aqo: true AQO mode: LEARN JOINS: 1 diff --git a/expected/unsupported.out b/expected/unsupported.out index ef6af46..42295e5 100644 --- a/expected/unsupported.out +++ b/expected/unsupported.out @@ -37,11 +37,11 @@ EXPLAIN (COSTS OFF) Aggregate AQO not used -> HashAggregate - AQO: rows=17 Group Key: t.x + AQO: rows=17 -> Seq Scan on t - AQO: rows=801 Filter: (x > 3) + AQO: rows=801 Using aqo: true AQO mode: LEARN JOINS: 0 @@ -54,12 +54,12 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) str -------------------------------------------------- HashAggregate (actual rows=17.00 loops=1) - AQO not used Group Key: x + AQO not used -> Seq Scan on t (actual rows=801.00 loops=1) - AQO not used Filter: (x > 3) Rows Removed by Filter: 199 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -81,8 +81,8 @@ EXPLAIN (COSTS OFF) Aggregate AQO not used -> HashAggregate - AQO: rows=10 Group Key: t1.x, t1.y + AQO: rows=10 -> Seq Scan on t1 AQO: rows=1000 Using aqo: true @@ -103,8 +103,8 @@ EXPLAIN (COSTS OFF) Aggregate AQO not used -> HashAggregate - AQO: rows=10 Group Key: t1.x, (t1.x * t1.y) + AQO: rows=10 -> Seq Scan on t1 AQO: rows=1000 Using aqo: true @@ -146,11 +146,11 @@ WHERE q2.x > 1; Aggregate AQO not used -> Aggregate - AQO not used Filter: (count(*) > 1) + AQO not used -> HashAggregate - AQO: rows=10 Group Key: t1.x, t1.y + AQO: rows=10 -> Seq Scan on t1 AQO: rows=1000 Using aqo: true @@ -174,11 +174,11 @@ EXPLAIN (COSTS OFF) Aggregate AQO not used -> MixedAggregate - AQO not used Hash Key: t1.x, t1.y Hash Key: t1.x Hash Key: t1.y Group Key: () + AQO not used -> Seq Scan on t1 AQO: rows=1000 Using aqo: true @@ -207,13 +207,13 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) -> Aggregate (actual rows=1.00 loops=1) AQO not used -> Seq Scan on t t_1 (actual rows=50.00 loops=1) - AQO: rows=50, error=0% Filter: (x = 1) Rows Removed by Filter: 950 + AQO: rows=50, error=0% -> Seq Scan on t (actual rows=50.00 loops=1) - AQO: rows=50, error=0% Filter: ((x)::numeric = (InitPlan 1).col1) Rows Removed by Filter: 950 + AQO: rows=50, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -234,15 +234,15 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) Aggregate (actual rows=1.00 loops=1) AQO not used -> Seq Scan on t (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Filter: ((x)::numeric = (SubPlan 1)) + AQO: rows=1000, error=0% SubPlan 1 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0 (actual rows=49.90 loops=1000) - AQO: rows=50, error=0% Filter: (x = t.x) Rows Removed by Filter: 950 + AQO: rows=50, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -258,23 +258,23 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) Aggregate (actual rows=1.00 loops=1) AQO not used -> Seq Scan on t (actual rows=0.00 loops=1) - AQO not used Filter: (((x)::numeric = (SubPlan 1)) OR (ANY ((x)::numeric = (SubPlan 2).col1))) Rows Removed by Filter: 1000 + AQO not used SubPlan 1 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0 (actual rows=0.00 loops=1000) - AQO not used Filter: (x = (t.x + 21)) Rows Removed by Filter: 1000 + AQO not used SubPlan 2 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0_1 (actual rows=0.00 loops=1000) - AQO not used Filter: (x = (t.x + 21)) Rows Removed by Filter: 1000 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -289,23 +289,23 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) Aggregate (actual rows=1.00 loops=1) AQO not used -> Seq Scan on t (actual rows=0.00 loops=1) - AQO: rows=1, error=100% Filter: (((x)::numeric = (SubPlan 1)) OR (ANY ((x)::numeric = (SubPlan 2).col1))) Rows Removed by Filter: 1000 + AQO: rows=1, error=100% SubPlan 1 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0 (actual rows=0.00 loops=1000) - AQO: rows=1, error=100% Filter: (x = (t.x + 21)) Rows Removed by Filter: 1000 + AQO: rows=1, error=100% SubPlan 2 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0_1 (actual rows=0.00 loops=1000) - AQO: rows=1, error=100% Filter: (x = (t.x + 21)) Rows Removed by Filter: 1000 + AQO: rows=1, error=100% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -321,23 +321,23 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) Aggregate (actual rows=1.00 loops=1) AQO not used -> Seq Scan on t (actual rows=0.00 loops=1) - AQO: rows=1, error=100% Filter: (((x)::numeric = (SubPlan 1)) OR (ANY ((x)::numeric = (SubPlan 2).col1))) Rows Removed by Filter: 1000 + AQO: rows=1, error=100% SubPlan 1 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0 (actual rows=0.00 loops=1000) - AQO: rows=1, error=100% Filter: (x = (t.x + 22)) Rows Removed by Filter: 1000 + AQO: rows=1, error=100% SubPlan 2 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0_1 (actual rows=0.00 loops=1000) - AQO: rows=1, error=100% Filter: (x = (t.x + 23)) Rows Removed by Filter: 1000 + AQO: rows=1, error=100% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -367,30 +367,30 @@ SELECT count(*) FROM Aggregate (actual rows=1.00 loops=1) AQO not used -> Hash Join (actual rows=42550.00 loops=1) - AQO: rows=42550, error=0% Hash Cond: ((t_1.x + 1) = t.x) + AQO: rows=42550, error=0% -> Seq Scan on t t_1 (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Filter: (((x % 3))::numeric < (SubPlan 2)) + AQO: rows=1000, error=0% SubPlan 2 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0_1 (actual rows=950.10 loops=1000) - AQO: rows=950, error=-0% Filter: (x <> t_1.x) Rows Removed by Filter: 50 + AQO: rows=950, error=-0% -> Hash (actual rows=851.00 loops=1) -> Seq Scan on t (actual rows=851.00 loops=1) - AQO: rows=851, error=0% Filter: (((x % 3))::numeric < (SubPlan 1)) Rows Removed by Filter: 149 + AQO: rows=851, error=0% SubPlan 1 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0 (actual rows=49.90 loops=1000) - AQO: rows=50, error=0% Filter: (x = t.x) Rows Removed by Filter: 950 + AQO: rows=50, error=0% Using aqo: true AQO mode: LEARN JOINS: 1 @@ -405,22 +405,22 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) Aggregate (actual rows=1.00 loops=1) AQO not used -> Seq Scan on t (actual rows=1000.00 loops=1) - AQO not used Filter: ((SubPlan 1) = (SubPlan 2)) + AQO not used SubPlan 1 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0 (actual rows=49.90 loops=1000) - AQO not used Filter: (x = t.x) Rows Removed by Filter: 950 + AQO not used SubPlan 2 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0_1 (actual rows=49.90 loops=1000) - AQO not used Filter: (x = t.x) Rows Removed by Filter: 950 + AQO not used Using aqo: true AQO mode: LEARN JOINS: 0 @@ -434,22 +434,22 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, BUFFERS OFF) Aggregate (actual rows=1.00 loops=1) AQO not used -> Seq Scan on t (actual rows=1000.00 loops=1) - AQO: rows=1000, error=0% Filter: ((SubPlan 1) = (SubPlan 2)) + AQO: rows=1000, error=0% SubPlan 1 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0 (actual rows=49.90 loops=1000) - AQO: rows=50, error=0% Filter: (x = t.x) Rows Removed by Filter: 950 + AQO: rows=50, error=0% SubPlan 2 -> Aggregate (actual rows=1.00 loops=1000) AQO not used -> Seq Scan on t t0_1 (actual rows=49.90 loops=1000) - AQO: rows=50, error=0% Filter: (x = t.x) Rows Removed by Filter: 950 + AQO: rows=50, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -476,15 +476,15 @@ SELECT * FROM QUERY PLAN ------------------------------------------------ Nested Loop (actual rows=0.00 loops=1) - AQO: rows=1, error=100% Join Filter: (t.x = t_1.x) + AQO: rows=1, error=100% -> Seq Scan on t (actual rows=0.00 loops=1) - AQO: rows=1, error=100% Filter: (x < 0) Rows Removed by Filter: 1000 + AQO: rows=1, error=100% -> Seq Scan on t t_1 (never executed) - AQO: rows=1 Filter: (x > 20) + AQO: rows=1 Using aqo: true AQO mode: LEARN JOINS: 0 @@ -513,12 +513,12 @@ EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF, BUFFERS OFF) Aggregate (actual rows=1.00 loops=1) AQO not used -> Index Only Scan using ind1 on t (actual rows=50.00 loops=1) - AQO: rows=50, error=0% Index Cond: (x < 3) Filter: (mod(x, 3) = 1) Rows Removed by Filter: 99 Heap Fetches: 149 Index Searches: 1 + AQO: rows=50, error=0% Using aqo: true AQO mode: LEARN JOINS: 0 @@ -540,13 +540,13 @@ WHERE str NOT LIKE '%Heap Blocks%'; str -------------------------------------------------------------------- Aggregate (actual rows=1.00 loops=1) - AQO not used Output: count(*) + AQO not used -> Bitmap Heap Scan on public.t (actual rows=50.00 loops=1) - AQO: rows=50, error=0% Recheck Cond: (mod(t.x, 3) = 1) Filter: (t.x < 3) Rows Removed by Filter: 300 + AQO: rows=50, error=0% -> Bitmap Index Scan on ind2 (actual rows=350.00 loops=1) Index Cond: (mod(t.x, 3) = 1) Index Searches: 1 @@ -564,9 +564,9 @@ EXPLAIN (COSTS OFF) Aggregate AQO not used -> Index Only Scan using ind1 on t - AQO: rows=50 Index Cond: (x < 3) Filter: (mod(x, 3) = 1) + AQO: rows=50 Using aqo: true AQO mode: LEARN JOINS: 0 diff --git a/postprocessing.c b/postprocessing.c index 3d50062..b369b3c 100644 --- a/postprocessing.c +++ b/postprocessing.c @@ -979,15 +979,18 @@ ExtractFromQueryEnv(QueryDesc *queryDesc) } void -print_node_explain(ExplainState *es, PlanState *ps, Plan *plan) +print_node_explain(PlanState *ps, List *ancestors, + const char *relationship, const char *plan_name, + struct ExplainState *es) { + Plan *plan = ps->plan; int wrkrs = 1; double error = -1.; AQOPlanNode *aqo_node; /* Extension, which took a hook early can be executed early too. */ - if (prev_ExplainOneNode_hook) - prev_ExplainOneNode_hook(es, ps, plan); + if (prev_explain_per_node_hook) + prev_explain_per_node_hook(ps, ancestors, relationship, plan_name, es); if (IsQueryDisabled() || !plan || es->format != EXPLAIN_FORMAT_TEXT) return; @@ -1019,44 +1022,58 @@ print_node_explain(ExplainState *es, PlanState *ps, Plan *plan) } explain_print: - appendStringInfoChar(es->str, '\n'); - if (es->str->len == 0 || es->str->data[es->str->len - 1] == '\n') - appendStringInfoSpaces(es->str, es->indent * 2); - - if (aqo_node->prediction > 0.) + if (es->format == EXPLAIN_FORMAT_TEXT) { - appendStringInfo(es->str, "AQO: rows=%.0lf", aqo_node->prediction); + ExplainIndentText(es); - if (ps->instrument && ps->instrument->nloops > 0.) + if (aqo_node->prediction > 0.) { - double rows = ps->instrument->ntuples / ps->instrument->nloops; + appendStringInfo(es->str, "AQO: rows=%.0lf", aqo_node->prediction); + + if (ps->instrument && ps->instrument->nloops > 0.) + { + double rows = ps->instrument->ntuples / ps->instrument->nloops; - error = 100. * (aqo_node->prediction - (rows*wrkrs)) - / aqo_node->prediction; - appendStringInfo(es->str, ", error=%.0lf%%", error); + error = 100. * (aqo_node->prediction - (rows*wrkrs)) + / aqo_node->prediction; + appendStringInfo(es->str, ", error=%.0lf%%", error); + } + appendStringInfoChar(es->str, '\n'); } + else + appendStringInfo(es->str, "AQO not used\n"); } else - appendStringInfo(es->str, "AQO not used"); + { + /* TODO */ + } explain_end: /* XXX: Do we really have situations when the plan is a NULL pointer? */ - if (plan && aqo_show_hash) - appendStringInfo(es->str, ", fss=%d", aqo_node->fss); + if (es->format == EXPLAIN_FORMAT_TEXT) + { + if (plan && aqo_show_hash) + { + ExplainIndentText(es); + appendStringInfo(es->str, ", fss=%d\n", aqo_node->fss); + } + } + else + { + /* TODO */ + } } /* * Prints if the plan was constructed with AQO. */ void -print_into_explain(PlannedStmt *plannedstmt, IntoClause *into, +print_into_explain(PlannedStmt *ps, IntoClause *into, ExplainState *es, const char *queryString, - ParamListInfo params, const instr_time *planduration, - QueryEnvironment *queryEnv) + ParamListInfo params, QueryEnvironment *queryEnv) { - if (prev_ExplainOnePlan_hook) - prev_ExplainOnePlan_hook(plannedstmt, into, es, queryString, - params, planduration, queryEnv); + if (prev_explain_per_plan_hook) + prev_explain_per_plan_hook(ps, into, es, queryString, params, queryEnv); if (IsQueryDisabled() || !aqo_show_details) return; From 2ecb9ce24a0bece462f4a5174907010ece723fa2 Mon Sep 17 00:00:00 2001 From: "Andrei V. Lepikhov" Date: Tue, 18 Mar 2025 12:44:52 +0100 Subject: [PATCH 3/3] Changes in the core patch we needed to fit the proposed explain hooks. --- aqo_master.patch | 69 ------------------------------------------------ 1 file changed, 69 deletions(-) diff --git a/aqo_master.patch b/aqo_master.patch index dd87274..db9caaa 100644 --- a/aqo_master.patch +++ b/aqo_master.patch @@ -1,49 +1,3 @@ -diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c -index 22616cf7add..8a28b783f72 100644 ---- a/src/backend/commands/explain.c -+++ b/src/backend/commands/explain.c -@@ -29,6 +29,7 @@ - #include "nodes/extensible.h" - #include "nodes/makefuncs.h" - #include "nodes/nodeFuncs.h" -+#include "optimizer/cost.h" - #include "parser/analyze.h" - #include "parser/parsetree.h" - #include "rewrite/rewriteHandler.h" -@@ -45,6 +46,12 @@ - #include "utils/typcache.h" - #include "utils/xml.h" - -+/* Hook for plugins to get control in ExplainOnePlan() */ -+ExplainOnePlan_hook_type ExplainOnePlan_hook = NULL; -+ -+/* Hook for plugins to get control in ExplainOnePlan() */ -+ExplainOneNode_hook_type ExplainOneNode_hook = NULL; -+ - - /* Hook for plugins to get control in ExplainOneQuery() */ - ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL; -@@ -690,6 +697,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, CachedPlan *cplan, - ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3, - es); - -+ if (ExplainOnePlan_hook) -+ ExplainOnePlan_hook(plannedstmt, into, es, -+ queryString, params, planduration, queryEnv); -+ - ExplainCloseGroup("Query", NULL, true, es); - } - -@@ -1884,6 +1895,9 @@ ExplainNode(PlanState *planstate, List *ancestors, - } - } - -+ if (ExplainOneNode_hook) -+ ExplainOneNode_hook(es, planstate, plan); -+ - /* in text format, first line ends here */ - if (es->format == EXPLAIN_FORMAT_TEXT) - appendStringInfoChar(es->str, '\n'); diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 256568d05a2..914f6124e67 100644 --- a/src/backend/optimizer/path/costsize.c @@ -520,29 +474,6 @@ index 5b35debc8ff..06a7bebe4f8 100644 /* * estimate_num_groups - Estimate number of groups in a grouped query * -diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h -index e8e92f966a1..323b3391b35 100644 ---- a/src/include/commands/explain.h -+++ b/src/include/commands/explain.h -@@ -49,6 +49,18 @@ extern PGDLLIMPORT explain_per_node_hook_type explain_per_node_hook; - typedef const char *(*explain_get_index_name_hook_type) (Oid indexId); - extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook; - -+/* Hook for plugins to get control in ExplainOnePlan() */ -+typedef void (*ExplainOnePlan_hook_type) (PlannedStmt *plannedstmt, IntoClause *into, -+ struct ExplainState *es, const char *queryString, -+ ParamListInfo params, const instr_time *planduration, -+ QueryEnvironment *queryEnv); -+extern PGDLLIMPORT ExplainOnePlan_hook_type ExplainOnePlan_hook; -+ -+/* Explain a node info */ -+typedef void (*ExplainOneNode_hook_type) (struct ExplainState *es, -+ PlanState *ps, -+ Plan *plan); -+extern PGDLLIMPORT ExplainOneNode_hook_type ExplainOneNode_hook; - - extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, - ParamListInfo params, DestReceiver *dest); diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index fbf05322c75..8fcb1fadda6 100644 --- a/src/include/nodes/pathnodes.h pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy