From 25a41dd5fb1d37375e55625c511ef487453908b1 Mon Sep 17 00:00:00 2001 From: Marina Polyakova Date: Fri, 1 Nov 2024 20:26:06 +0300 Subject: [PATCH] Add new expected output for unsupported regresison test --- expected/unsupported.out | 4 +- expected/unsupported_1.out | 710 +++++++++++++++++++++++++++++++++++++ sql/unsupported.sql | 2 + 3 files changed, 715 insertions(+), 1 deletion(-) create mode 100644 expected/unsupported_1.out diff --git a/expected/unsupported.out b/expected/unsupported.out index a088a47c..50f9af32 100644 --- a/expected/unsupported.out +++ b/expected/unsupported.out @@ -339,11 +339,13 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) (18 rows) -- No prediction for top SeqScan, because it fss is changed +SELECT str FROM expln(' EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) SELECT * FROM t WHERE x = (SELECT x FROM t t0 WHERE t0.x = t.x LIMIT 1) AND x IN (SELECT x FROM t t0 WHERE t0.x = t.x); - QUERY PLAN +') AS str WHERE str NOT LIKE '%Memory Usage%'; + str ----------------------------------------------------------- Seq Scan on t (actual rows=1000 loops=1) AQO not used diff --git a/expected/unsupported_1.out b/expected/unsupported_1.out new file mode 100644 index 00000000..b63f0ef8 --- /dev/null +++ b/expected/unsupported_1.out @@ -0,0 +1,710 @@ +CREATE EXTENSION IF NOT EXISTS aqo; +SELECT true AS success FROM aqo_reset(); + success +--------- + t +(1 row) + +-- Utility tool. Allow to filter system-dependent strings from an explain output. +CREATE OR REPLACE FUNCTION expln(query_string text) RETURNS SETOF text AS $$ +BEGIN + RETURN QUERY + EXECUTE format('%s', query_string); + RETURN; +END; +$$ LANGUAGE PLPGSQL; +SET aqo.mode = 'learn'; +SET aqo.show_details = 'on'; +DROP TABLE IF EXISTS t; +NOTICE: table "t" does not exist, skipping +CREATE TABLE t AS SELECT (gs.* / 50) AS x FROM generate_series(1,1000) AS gs; +ANALYZE t; +CREATE TABLE t1 AS SELECT mod(gs,10) AS x, mod(gs+1,10) AS y + FROM generate_series(1,1000) AS gs; +ANALYZE t, t1; +-- +-- Do not support HAVING clauses for now. +-- +SELECT count(*) FROM (SELECT * FROM t GROUP BY (x) HAVING x > 3) AS q1; + count +------- + 17 +(1 row) + +EXPLAIN (COSTS OFF) + SELECT count(*) FROM (SELECT * FROM t GROUP BY (x) HAVING x > 3) AS q1; + QUERY PLAN +------------------------------- + Aggregate + AQO not used + -> HashAggregate + AQO: rows=17 + Group Key: t.x + -> Seq Scan on t + AQO: rows=801 + Filter: (x > 3) + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(11 rows) + +SELECT str FROM expln(' +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT * FROM t GROUP BY (x) HAVING x > 3; +') AS str WHERE str NOT LIKE '%Memory Usage%'; + str +----------------------------------------------- + HashAggregate (actual rows=17 loops=1) + AQO not used + Group Key: x + -> Seq Scan on t (actual rows=801 loops=1) + AQO not used + Filter: (x > 3) + Rows Removed by Filter: 199 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(10 rows) + +-- +-- Doesn't estimates GROUP BY clause +-- +SELECT count(*) FROM (SELECT count(*) FROM t1 GROUP BY (x,y)) AS q1; + count +------- + 10 +(1 row) + +EXPLAIN (COSTS OFF) + SELECT count(*) FROM (SELECT count(*) FROM t1 GROUP BY (x,y)) AS q1; + QUERY PLAN +------------------------------- + Aggregate + AQO not used + -> HashAggregate + AQO: rows=10 + Group Key: t1.x, t1.y + -> Seq Scan on t1 + AQO: rows=1000 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(10 rows) + +SELECT count(*) FROM (SELECT count(*) FROM t1 GROUP BY (x,x*y)) AS q1; + count +------- + 10 +(1 row) + +EXPLAIN (COSTS OFF) + SELECT count(*) FROM (SELECT count(*) FROM t1 GROUP BY (x,x*y)) AS q1; + QUERY PLAN +---------------------------------------- + Aggregate + AQO not used + -> HashAggregate + AQO: rows=10 + Group Key: t1.x, (t1.x * t1.y) + -> Seq Scan on t1 + AQO: rows=1000 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(10 rows) + +SELECT count(*) FROM ( + SELECT count(*) AS x FROM ( + SELECT count(*) FROM t1 GROUP BY (x,y) + ) AS q1 +) AS q2 +WHERE q2.x > 1; + count +------- + 1 +(1 row) + +SELECT count(*) FROM ( + SELECT count(*) AS x FROM ( + SELECT count(*) FROM t1 GROUP BY (x,y) + ) AS q1 +) AS q2 +WHERE q2.x > 1; + count +------- + 1 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM ( + SELECT count(*) AS x FROM ( + SELECT count(*) FROM t1 GROUP BY (x,y) + ) AS q1 +) AS q2 +WHERE q2.x > 1; + QUERY PLAN +------------------------------------- + Aggregate + AQO not used + -> Aggregate + AQO not used + Filter: (count(*) > 1) + -> HashAggregate + AQO: rows=10 + Group Key: t1.x, t1.y + -> Seq Scan on t1 + AQO: rows=1000 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(13 rows) + +-- +-- Doesn't support GROUPING SETS clause +-- +SELECT count(*) FROM (SELECT x, y FROM t1 GROUP BY GROUPING SETS ((x,y), (x), (y), ())) AS q1; + count +------- + 31 +(1 row) + +EXPLAIN (COSTS OFF) + SELECT count(*) FROM (SELECT x, y FROM t1 GROUP BY GROUPING SETS ((x,y), (x), (y), ())) AS q1; + QUERY PLAN +------------------------------ + Aggregate + AQO not used + -> MixedAggregate + AQO not used + Hash Key: t1.x, t1.y + Hash Key: t1.x + Hash Key: t1.y + Group Key: () + -> Seq Scan on t1 + AQO: rows=1000 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(13 rows) + +-- +-- The subplans issue +-- +SELECT count(*) FROM t WHERE x = (SELECT avg(x) FROM t WHERE x = 1); + count +------- + 50 +(1 row) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT count(*) FROM t WHERE x = ( + SELECT avg(x) FROM t WHERE x = 1 + ); + QUERY PLAN +---------------------------------------------------------- + Aggregate (actual rows=1 loops=1) + AQO not used + InitPlan 1 (returns $0) + -> Aggregate (actual rows=1 loops=1) + AQO not used + -> Seq Scan on t t_1 (actual rows=50 loops=1) + AQO: rows=50, error=0% + Filter: (x = 1) + Rows Removed by Filter: 950 + -> Seq Scan on t (actual rows=50 loops=1) + AQO: rows=50, error=0% + Filter: ((x)::numeric = $0) + Rows Removed by Filter: 950 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(16 rows) + +SELECT count(*) FROM t WHERE x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x); + count +------- + 1000 +(1 row) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT count(*) FROM t WHERE x = ( + SELECT avg(x) FROM t t0 WHERE t0.x = t.x + ); + QUERY PLAN +------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + AQO not used + -> Seq Scan on t (actual rows=1000 loops=1) + AQO: rows=1000, error=0% + Filter: ((x)::numeric = (SubPlan 1)) + SubPlan 1 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0 (actual rows=50 loops=1000) + AQO: rows=50, error=0% + Filter: (x = t.x) + Rows Removed by Filter: 950 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(15 rows) + +-- Two identical subplans in a clause list +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT count(*) FROM t WHERE + x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21) OR + x IN (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21); + QUERY PLAN +------------------------------------------------------------------- + Aggregate (actual rows=1 loops=1) + AQO not used + -> Seq Scan on t (actual rows=0 loops=1) + AQO not used + Filter: (((x)::numeric = (SubPlan 1)) OR (SubPlan 2)) + Rows Removed by Filter: 1000 + SubPlan 1 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0 (actual rows=0 loops=1000) + AQO not used + Filter: (x = (t.x + 21)) + Rows Removed by Filter: 1000 + SubPlan 2 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0_1 (actual rows=0 loops=1000) + AQO not used + Filter: (x = (t.x + 21)) + Rows Removed by Filter: 1000 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(23 rows) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT count(*) FROM t WHERE + x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21) OR + x IN (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21); + QUERY PLAN +------------------------------------------------------------------- + Aggregate (actual rows=1 loops=1) + AQO not used + -> Seq Scan on t (actual rows=0 loops=1) + AQO: rows=1, error=100% + Filter: (((x)::numeric = (SubPlan 1)) OR (SubPlan 2)) + Rows Removed by Filter: 1000 + SubPlan 1 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0 (actual rows=0 loops=1000) + AQO: rows=1, error=100% + Filter: (x = (t.x + 21)) + Rows Removed by Filter: 1000 + SubPlan 2 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0_1 (actual rows=0 loops=1000) + AQO: rows=1, error=100% + Filter: (x = (t.x + 21)) + Rows Removed by Filter: 1000 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(23 rows) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT * FROM t WHERE + x = (SELECT x FROM t t0 WHERE t0.x = t.x LIMIT 1) AND + x IN (SELECT x FROM t t0 WHERE t0.x = t.x); + QUERY PLAN +------------------------------------------------------------------- + Nested Loop Semi Join (actual rows=1000 loops=1) + AQO not used + Join Filter: (t.x = t0.x) + Rows Removed by Join Filter: 475049 + -> Seq Scan on t (actual rows=1000 loops=1) + AQO not used + Filter: (x = (SubPlan 1)) + SubPlan 1 + -> Limit (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0_1 (actual rows=1 loops=1000) + AQO not used + Filter: (x = t.x) + Rows Removed by Filter: 475 + -> Seq Scan on t t0 (actual rows=476 loops=1000) + AQO not used + Using aqo: true + AQO mode: LEARN + JOINS: 1 +(19 rows) + +-- No prediction for top SeqScan, because it fss is changed +SELECT str FROM expln(' +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT * FROM t WHERE + x = (SELECT x FROM t t0 WHERE t0.x = t.x LIMIT 1) AND + x IN (SELECT x FROM t t0 WHERE t0.x = t.x); +') AS str WHERE str NOT LIKE '%Memory Usage%'; + str +------------------------------------------------------------------- + Hash Join (actual rows=1000 loops=1) + AQO: rows=1000, error=0% + Hash Cond: (t.x = t0.x) + -> Seq Scan on t (actual rows=1000 loops=1) + AQO: rows=1000, error=0% + Filter: (x = (SubPlan 1)) + SubPlan 1 + -> Limit (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0_1 (actual rows=1 loops=1000) + AQO: rows=1, error=0% + Filter: (x = t.x) + Rows Removed by Filter: 475 + -> Hash (actual rows=21 loops=1) + -> HashAggregate (actual rows=21 loops=1) + AQO: rows=476, error=96% + Group Key: t0.x, t0.x + -> Seq Scan on t t0 (actual rows=1000 loops=1) + AQO: rows=476, error=-110% + Using aqo: true + AQO mode: LEARN + JOINS: 1 +(22 rows) + +-- It's OK to use the knowledge for a query with different constants. +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT count(*) FROM t WHERE + x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 22) OR + x IN (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 23); + QUERY PLAN +------------------------------------------------------------------- + Aggregate (actual rows=1 loops=1) + AQO not used + -> Seq Scan on t (actual rows=0 loops=1) + AQO: rows=1, error=100% + Filter: (((x)::numeric = (SubPlan 1)) OR (SubPlan 2)) + Rows Removed by Filter: 1000 + SubPlan 1 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0 (actual rows=0 loops=1000) + AQO: rows=1, error=100% + Filter: (x = (t.x + 22)) + Rows Removed by Filter: 1000 + SubPlan 2 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0_1 (actual rows=0 loops=1000) + AQO: rows=1, error=100% + Filter: (x = (t.x + 23)) + Rows Removed by Filter: 1000 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(23 rows) + +-- Different SubPlans in the quals of leafs of JOIN. +SELECT count(*) FROM + (SELECT * FROM t WHERE x % 3 < (SELECT avg(x) FROM t t0 WHERE t0.x = t.x)) AS q1 + JOIN + (SELECT * FROM t WHERE x % 3 < (SELECT avg(x) FROM t t0 WHERE t0.x <> t.x)) AS q2 + ON q1.x = q2.x+1; + count +------- + 42550 +(1 row) + +SELECT str FROM expln(' +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +SELECT count(*) FROM + (SELECT * FROM t WHERE x % 3 < (SELECT avg(x) FROM t t0 WHERE t0.x = t.x)) AS q1 + JOIN + (SELECT * FROM t WHERE x % 3 < (SELECT avg(x) FROM t t0 WHERE t0.x <> t.x)) AS q2 + ON q1.x = q2.x+1; +') AS str WHERE str NOT LIKE '%Memory Usage%'; + str +------------------------------------------------------------------------------ + Aggregate (actual rows=1 loops=1) + AQO not used + -> Hash Join (actual rows=42550 loops=1) + AQO: rows=42550, error=0% + Hash Cond: ((t_1.x + 1) = t.x) + -> Seq Scan on t t_1 (actual rows=1000 loops=1) + AQO: rows=1000, error=0% + Filter: (((x % 3))::numeric < (SubPlan 2)) + SubPlan 2 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0_1 (actual rows=950 loops=1000) + AQO: rows=950, error=-0% + Filter: (x <> t_1.x) + Rows Removed by Filter: 50 + -> Hash (actual rows=851 loops=1) + -> Seq Scan on t (actual rows=851 loops=1) + AQO: rows=851, error=0% + Filter: (((x % 3))::numeric < (SubPlan 1)) + Rows Removed by Filter: 149 + SubPlan 1 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0 (actual rows=50 loops=1000) + AQO: rows=50, error=0% + Filter: (x = t.x) + Rows Removed by Filter: 950 + Using aqo: true + AQO mode: LEARN + JOINS: 1 +(30 rows) + +-- Two identical subplans in a clause +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT count(*) FROM t WHERE (SELECT avg(x) FROM t t0 WHERE t0.x = t.x) = + (SELECT avg(x) FROM t t0 WHERE t0.x = t.x); + QUERY PLAN +-------------------------------------------------------------------- + Aggregate (actual rows=1 loops=1) + AQO not used + -> Seq Scan on t (actual rows=1000 loops=1) + AQO not used + Filter: ((SubPlan 1) = (SubPlan 2)) + SubPlan 1 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0 (actual rows=50 loops=1000) + AQO not used + Filter: (x = t.x) + Rows Removed by Filter: 950 + SubPlan 2 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0_1 (actual rows=50 loops=1000) + AQO not used + Filter: (x = t.x) + Rows Removed by Filter: 950 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(22 rows) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT count(*) FROM t WHERE (SELECT avg(x) FROM t t0 WHERE t0.x = t.x) = + (SELECT avg(x) FROM t t0 WHERE t0.x = t.x); + QUERY PLAN +-------------------------------------------------------------------- + Aggregate (actual rows=1 loops=1) + AQO not used + -> Seq Scan on t (actual rows=1000 loops=1) + AQO: rows=1000, error=0% + Filter: ((SubPlan 1) = (SubPlan 2)) + SubPlan 1 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0 (actual rows=50 loops=1000) + AQO: rows=50, error=0% + Filter: (x = t.x) + Rows Removed by Filter: 950 + SubPlan 2 + -> Aggregate (actual rows=1 loops=1000) + AQO not used + -> Seq Scan on t t0_1 (actual rows=50 loops=1000) + AQO: rows=50, error=0% + Filter: (x = t.x) + Rows Removed by Filter: 950 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(22 rows) + +-- +-- Not executed nodes +-- +SELECT * FROM + (SELECT * FROM t WHERE x < 0) AS t0 + JOIN + (SELECT * FROM t WHERE x > 20) AS t1 + USING(x); + x +--- +(0 rows) + +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +SELECT * FROM + (SELECT * FROM t WHERE x < 0) AS t0 + JOIN + (SELECT * FROM t WHERE x > 20) AS t1 + USING(x); + QUERY PLAN +--------------------------------------------- + Nested Loop (actual rows=0 loops=1) + AQO: rows=1, error=100% + Join Filter: (t.x = t_1.x) + -> Seq Scan on t (actual rows=0 loops=1) + AQO: rows=1, error=100% + Filter: (x < 0) + Rows Removed by Filter: 1000 + -> Seq Scan on t t_1 (never executed) + AQO: rows=1 + Filter: (x > 20) + Using aqo: true + AQO mode: LEARN + JOINS: 1 +(13 rows) + +-- AQO needs to predict total fetched tuples in a table. +-- +-- At a non-leaf node we have prediction about input tuples - is a number of +-- predicted output rows in underlying node. But for Scan nodes we don't have +-- any prediction on number of fetched tuples. +-- So, if selectivity was wrong we could make bad choice of Scan operation. +-- For example, we could choose suboptimal index. +-- Turn off statistics gathering for simple demonstration of filtering problem. +ALTER TABLE t SET (autovacuum_enabled = 'false'); +CREATE INDEX ind1 ON t(x); +SELECT count(*) FROM t WHERE x < 3 AND mod(x,3) = 1; + count +------- + 50 +(1 row) + +EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) + SELECT count(*) FROM t WHERE x < 3 AND mod(x,3) = 1; + QUERY PLAN +---------------------------------------------------------------- + Aggregate (actual rows=1 loops=1) + AQO not used + -> Index Only Scan using ind1 on t (actual rows=50 loops=1) + AQO: rows=50, error=0% + Index Cond: (x < 3) + Filter: (mod(x, 3) = 1) + Rows Removed by Filter: 99 + Heap Fetches: 149 + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(11 rows) + +-- Because of bad statistics we use a last created index instead of best choice. +-- Here we filter more tuples than with the ind1 index. +CREATE INDEX ind2 ON t(mod(x,3)); +SELECT count(*) FROM t WHERE x < 3 AND mod(x,3) = 1; + count +------- + 50 +(1 row) + +SELECT str FROM expln(' + EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, SUMMARY OFF, TIMING OFF) + SELECT count(*) FROM t WHERE x < 3 AND mod(x,3) = 1') AS str +WHERE str NOT LIKE '%Heap Blocks%'; + str +----------------------------------------------------------------- + Aggregate (actual rows=1 loops=1) + AQO not used + Output: count(*) + -> Bitmap Heap Scan on public.t (actual rows=50 loops=1) + AQO: rows=50, error=0% + Recheck Cond: (mod(t.x, 3) = 1) + Filter: (t.x < 3) + Rows Removed by Filter: 300 + -> Bitmap Index Scan on ind2 (actual rows=350 loops=1) + Index Cond: (mod(t.x, 3) = 1) + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(13 rows) + +-- Best choice is ... +ANALYZE t; +EXPLAIN (COSTS OFF) + SELECT count(*) FROM t WHERE x < 3 AND mod(x,3) = 1; + QUERY PLAN +--------------------------------------- + Aggregate + AQO not used + -> Index Only Scan using ind1 on t + AQO: rows=50 + Index Cond: (x < 3) + Filter: (mod(x, 3) = 1) + Using aqo: true + AQO mode: LEARN + JOINS: 0 +(9 rows) + +-- XXX: Do we stuck into an unstable behavior of an error value? +-- Live with this variant of the test for some time. +SELECT round(error::numeric, 3) AS error, query_text +FROM aqo_cardinality_error(true) cef, aqo_query_texts aqt +WHERE aqt.queryid = cef.id +ORDER BY (md5(query_text),error) DESC; + error | query_text +-------+------------------------------------------------------------------------------------------------ + 0.768 | SELECT count(*) FROM (SELECT count(*) FROM t1 GROUP BY (x,y)) AS q1; + 0.070 | SELECT count(*) FROM (SELECT * FROM t GROUP BY (x) HAVING x > 3) AS q1; + 0.644 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + + | SELECT * FROM t WHERE + + | x = (SELECT x FROM t t0 WHERE t0.x = t.x LIMIT 1) AND + + | x IN (SELECT x FROM t t0 WHERE t0.x = t.x); + 0.000 | SELECT count(*) FROM t WHERE x < 3 AND mod(x,3) = 1; + 0.000 | SELECT * FROM + + | (SELECT * FROM t WHERE x < 0) AS t0 + + | JOIN + + | (SELECT * FROM t WHERE x > 20) AS t1 + + | USING(x); + 0.000 | SELECT count(*) FROM t WHERE x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x); + 0.000 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + + | SELECT count(*) FROM t WHERE + + | x = (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21) OR + + | x IN (SELECT avg(x) FROM t t0 WHERE t0.x = t.x + 21); + 0.454 | SELECT count(*) FROM (SELECT x, y FROM t1 GROUP BY GROUPING SETS ((x,y), (x), (y), ())) AS q1; + 0.000 | SELECT count(*) FROM ( + + | SELECT count(*) AS x FROM ( + + | SELECT count(*) FROM t1 GROUP BY (x,y) + + | ) AS q1 + + | ) AS q2 + + | WHERE q2.x > 1; + 0.768 | SELECT count(*) FROM (SELECT count(*) FROM t1 GROUP BY (x,x*y)) AS q1; + 0.000 | SELECT count(*) FROM t WHERE x = (SELECT avg(x) FROM t WHERE x = 1); + 0.000 | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + + | SELECT count(*) FROM t WHERE (SELECT avg(x) FROM t t0 WHERE t0.x = t.x) = + + | (SELECT avg(x) FROM t t0 WHERE t0.x = t.x); + 0.106 | + + | EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) + + | SELECT * FROM t GROUP BY (x) HAVING x > 3; + + | + 0.000 | SELECT count(*) FROM + + | (SELECT * FROM t WHERE x % 3 < (SELECT avg(x) FROM t t0 WHERE t0.x = t.x)) AS q1 + + | JOIN + + | (SELECT * FROM t WHERE x % 3 < (SELECT avg(x) FROM t t0 WHERE t0.x <> t.x)) AS q2 + + | ON q1.x = q2.x+1; +(14 rows) + +DROP TABLE t,t1 CASCADE; -- delete all tables used in the test +SELECT count(*) FROM aqo_data; -- Just to detect some changes in the logic. May some false positives really bother us here? + count +------- + 49 +(1 row) + +SELECT true AS success FROM aqo_cleanup(); + success +--------- + t +(1 row) + +SELECT count(*) FROM aqo_data; -- No one row should be returned + count +------- + 0 +(1 row) + +-- Look for any remaining queries in the ML storage. +SELECT to_char(error, '9.99EEEE')::text AS error, query_text +FROM aqo_cardinality_error(true) cef, aqo_query_texts aqt +WHERE aqt.queryid = cef.id +ORDER BY (md5(query_text),error) DESC; + error | query_text +-------+------------ +(0 rows) + +DROP EXTENSION aqo; diff --git a/sql/unsupported.sql b/sql/unsupported.sql index e5853306..44ca0aac 100644 --- a/sql/unsupported.sql +++ b/sql/unsupported.sql @@ -103,10 +103,12 @@ EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) x = (SELECT x FROM t t0 WHERE t0.x = t.x LIMIT 1) AND x IN (SELECT x FROM t t0 WHERE t0.x = t.x); -- No prediction for top SeqScan, because it fss is changed +SELECT str FROM expln(' EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) SELECT * FROM t WHERE x = (SELECT x FROM t t0 WHERE t0.x = t.x LIMIT 1) AND x IN (SELECT x FROM t t0 WHERE t0.x = t.x); +') AS str WHERE str NOT LIKE '%Memory Usage%'; -- It's OK to use the knowledge for a query with different constants. EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)