From aae3233c4f8cb0a4b7e232f60b3451d86bccc1ff Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Sat, 4 May 2024 19:50:55 +0700 Subject: [PATCH] MDEV-34041 Display additional information for materialized subqueries in EXPLAIN/ANALYZE FORMAT=JSON This commits adds the "materialization" block to the output of EXPLAIN/ANALYZE FORMAT=JSON when materialized subqueries are involved into processing. In the case of ANALYZE additional runtime information is displayed, such as: - chosen strategy of materialization - number of partial match/index lookup loops - sizes of partial match buffers --- mysql-test/include/analyze-format.inc | 2 +- mysql-test/main/analyze_format_json.result | 30 +- mysql-test/main/derived_cond_pushdown.result | 210 ++-- mysql-test/main/explain_json.result | 34 +- mysql-test/main/having_cond_pushdown.result | 84 +- mysql-test/main/in_subq_cond_pushdown.result | 966 ++++++++++-------- .../main/subselect_mat_analyze_json.result | 945 +++++++++++++++++ .../main/subselect_mat_analyze_json.test | 99 ++ sql/item_subselect.cc | 47 +- sql/item_subselect.h | 119 ++- sql/sql_array.h | 12 + sql/sql_explain.cc | 55 + sql/sql_explain.h | 31 + sql/sql_select.cc | 5 + 14 files changed, 2024 insertions(+), 615 deletions(-) create mode 100644 mysql-test/main/subselect_mat_analyze_json.result create mode 100644 mysql-test/main/subselect_mat_analyze_json.test diff --git a/mysql-test/include/analyze-format.inc b/mysql-test/include/analyze-format.inc index 330be82ef96..89d290a87ea 100644 --- a/mysql-test/include/analyze-format.inc +++ b/mysql-test/include/analyze-format.inc @@ -1,3 +1,3 @@ # The time on ANALYSE FORMAT=JSON is rather variable ---replace_regex /("(r_[a-z_]*_time_ms|r_buffer_size)": )[^, \n]*/\1"REPLACED"/ +--replace_regex /("(r_[a-z_]*_time_ms|r_buffer_size|r_partial_match_buffer_size)": )[^, \n]*/\1"REPLACED"/ diff --git a/mysql-test/main/analyze_format_json.result b/mysql-test/main/analyze_format_json.result index 5b125b26e18..8c4fc5d051a 100644 --- a/mysql-test/main/analyze_format_json.result +++ b/mysql-test/main/analyze_format_json.result @@ -659,20 +659,24 @@ ANALYZE }, "subqueries": [ { - "query_block": { - "select_id": 2, - "r_loops": 1, - "r_total_time_ms": "REPLACED", - "table": { - "table_name": "t1", - "access_type": "ALL", + "materialization": { + "r_strategy": "index_lookup", + "r_loops": 2, + "query_block": { + "select_id": 2, "r_loops": 1, - "rows": 2, - "r_rows": 2, - "r_table_time_ms": "REPLACED", - "r_other_time_ms": "REPLACED", - "filtered": 100, - "r_filtered": 100 + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } } } } diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 9932eb04024..f13f04a26dc 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -7671,10 +7671,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 2, + "table": { + "message": "Select tables optimized away" + } } } } @@ -7731,10 +7733,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 2, + "table": { + "message": "Select tables optimized away" + } } } } @@ -7815,10 +7819,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 3, + "table": { + "message": "Select tables optimized away" + } } } } @@ -7872,10 +7878,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 3, + "table": { + "message": "Select tables optimized away" + } } } } @@ -7924,10 +7932,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 3, + "table": { + "message": "Select tables optimized away" + } } } } @@ -7976,10 +7986,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 3, + "table": { + "message": "Select tables optimized away" + } } } } @@ -8030,10 +8042,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 3, + "table": { + "message": "Select tables optimized away" + } } } } @@ -8082,10 +8096,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 3, + "table": { + "message": "Select tables optimized away" + } } } } @@ -8134,10 +8150,12 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "table": { - "message": "Select tables optimized away" + "materialization": { + "query_block": { + "select_id": 3, + "table": { + "message": "Select tables optimized away" + } } } } @@ -8223,10 +8241,12 @@ EXPLAIN }, "subqueries": [ { - "query_block": { - "select_id": 2, - "table": { - "message": "Impossible WHERE" + "materialization": { + "query_block": { + "select_id": 2, + "table": { + "message": "Impossible WHERE" + } } } } @@ -9294,27 +9314,29 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "", - "access_type": "ALL", - "rows": 5, - "filtered": 100, - "attached_condition": "d_tab.e > 1", - "materialized": { - "query_block": { - "select_id": 3, - "filesort": { - "sort_key": "t2.e", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 5, - "filtered": 100, - "attached_condition": "t2.e > 1" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "t2.e > 1" + } } } } @@ -9396,27 +9418,29 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "", - "access_type": "ALL", - "rows": 5, - "filtered": 100, - "attached_condition": "d_tab.max_f > 20", - "materialized": { - "query_block": { - "select_id": 3, - "having_condition": "max_f > 20", - "filesort": { - "sort_key": "t2.e", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 5, - "filtered": 100 + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 5, + "filtered": 100, + "attached_condition": "d_tab.max_f > 20", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_f > 20", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 5, + "filtered": 100 + } } } } @@ -10826,16 +10850,18 @@ EXPLAIN "attached_condition": "t4.c = ``.`sum(b)`", "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`f1(a)` > 1 and `sum(b)` > 123", - "temporary_table": { - "table": { - "table_name": "t1", - "access_type": "ALL", - "rows": 3, - "filtered": 100, - "attached_condition": "t1.a + 1 > 10" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`f1(a)` > 1 and `sum(b)` > 123", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 3, + "filtered": 100, + "attached_condition": "t1.a + 1 > 10" + } } } } diff --git a/mysql-test/main/explain_json.result b/mysql-test/main/explain_json.result index 0bf565b701d..e93d62426af 100644 --- a/mysql-test/main/explain_json.result +++ b/mysql-test/main/explain_json.result @@ -574,14 +574,16 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t1", - "access_type": "ALL", - "rows": 10, - "filtered": 100 + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 10, + "filtered": 100 + } } } } @@ -906,13 +908,15 @@ EXPLAIN }, "subqueries": [ { - "query_block": { - "select_id": 2, - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 2, - "filtered": 100 + "materialization": { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 2, + "filtered": 100 + } } } } diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result index 9713f014f43..3531c855781 100644 --- a/mysql-test/main/having_cond_pushdown.result +++ b/mysql-test/main/having_cond_pushdown.result @@ -1134,15 +1134,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 4, - "filtered": 100, - "attached_condition": "t2.x < 5 and t2.x > 1" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "t2.x < 5 and t2.x > 1" + } } } } @@ -1183,15 +1185,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 4, - "filtered": 100, - "attached_condition": "t2.x < 5 and t2.x > 1" + "materialization": { + "query_block": { + "select_id": 3, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "t2.x < 5 and t2.x > 1" + } } } } @@ -1257,16 +1261,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.y)` < 14", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 4, - "filtered": 100, - "attached_condition": "t2.x < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.y)` < 14", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "t2.x < 5" + } } } } @@ -1307,16 +1313,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "having_condition": "`MAX(t2.y)` < 14", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 4, - "filtered": 100, - "attached_condition": "t2.x < 5" + "materialization": { + "query_block": { + "select_id": 3, + "having_condition": "`MAX(t2.y)` < 14", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "t2.x < 5" + } } } } diff --git a/mysql-test/main/in_subq_cond_pushdown.result b/mysql-test/main/in_subq_cond_pushdown.result index eef320d2d04..0e1d1df1875 100644 --- a/mysql-test/main/in_subq_cond_pushdown.result +++ b/mysql-test/main/in_subq_cond_pushdown.result @@ -70,16 +70,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.g)` < 25", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` < 25", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -159,16 +161,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.g)` > 55 and t2.f < 4", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` > 55 and t2.f < 4", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -250,16 +254,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.g)` > 60 or `MAX(t2.g)` < 25", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` > 60 or `MAX(t2.g)` < 25", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -339,16 +345,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "(`MAX(t2.g)` > 60 or `MAX(t2.g)` < 25) and t2.f > 2", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "(`MAX(t2.g)` > 60 or `MAX(t2.g)` < 25) and t2.f > 2", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -430,16 +438,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "t2.f > 1", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "t2.f > 1", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -519,16 +529,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(v1_y)` > 20", - "temporary_table": { - "table": { - "table_name": "t3", - "access_type": "ALL", - "rows": 8, - "filtered": 100, - "attached_condition": "t3.x > 1 and t3.x <= 3" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(v1_y)` > 20", + "temporary_table": { + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t3.x > 1 and t3.x <= 3" + } } } } @@ -621,16 +633,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.g)` > 20", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` > 20", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -712,15 +726,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e < 2" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e < 2" + } } } } @@ -802,15 +818,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e > 2 and t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e > 2 and t2.e < 5" + } } } } @@ -894,15 +912,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e >= 4)" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e >= 4)" + } } } } @@ -982,15 +1002,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e = 5) and t2.f > 3" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e = 5) and t2.f > 3" + } } } } @@ -1070,15 +1092,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e = 5) and t2.f > 3" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and (t2.e < 2 or t2.e = 5) and t2.f > 3" + } } } } @@ -1158,15 +1182,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e < 2" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e < 2" + } } } } @@ -1246,14 +1272,16 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e = 1" + "materialization": { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e = 1" + } } } } @@ -1332,15 +1360,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e > 1" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e > 1" + } } } } @@ -1418,15 +1448,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t3", - "access_type": "ALL", - "rows": 8, - "filtered": 100, - "attached_condition": "t3.x > 1 and t3.x <= 3 and t3.x < 3" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 8, + "filtered": 100, + "attached_condition": "t3.x > 1 and t3.x <= 3 and t3.x < 3" + } } } } @@ -1521,15 +1553,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e <= 3" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e <= 3" + } } } } @@ -1610,16 +1644,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "t2.f < 3 or t2.f = 4", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e < 3" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "t2.f < 3 or t2.f = 4", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e < 3" + } } } } @@ -1699,16 +1735,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "t2.e + `MAX(t2.g)` > 41", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "t2.e + `MAX(t2.g)` > 41", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -1790,16 +1828,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.g)` - t2.e < 35", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` - t2.e < 35", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -1879,16 +1919,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.g)` * t2.e > 100", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` * t2.e > 100", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -1972,16 +2014,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.g)` / t2.e > 30", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` / t2.e > 30", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -2061,16 +2105,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "`MAX(t2.g)` between 50 and 100", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "`MAX(t2.g)` between 50 and 100", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -2150,15 +2196,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e + t2.f > 5" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e + t2.f > 5" + } } } } @@ -2238,15 +2286,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e - t2.f > 0" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e - t2.f > 0" + } } } } @@ -2326,15 +2376,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e * t2.f > 6" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e * t2.f > 6" + } } } } @@ -2416,15 +2468,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.f / t2.e > 2" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.f / t2.e > 2" + } } } } @@ -2510,15 +2564,17 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e between 1 and 3" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e between 1 and 3" + } } } } @@ -2602,29 +2658,31 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "v2.max_g > 3", - "temporary_table": { - "table": { - "table_name": "", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "v2.e < 5", - "materialized": { - "query_block": { - "select_id": 3, - "having_condition": "max_g > 25", - "filesort": { - "sort_key": "t2.e", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "v2.max_g > 3", + "temporary_table": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "v2.e < 5", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5" + } } } } @@ -2712,28 +2770,30 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "v2.e < 5 and v2.e > 1", - "materialized": { - "query_block": { - "select_id": 3, - "having_condition": "max_g > 25", - "filesort": { - "sort_key": "t2.e", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e > 1" + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "v2.e < 5 and v2.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e > 1" + } } } } @@ -2822,29 +2882,31 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "having_condition": "v2.max_g < 100", - "temporary_table": { - "table": { - "table_name": "", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "v2.e < 5 and v2.e > 1", - "materialized": { - "query_block": { - "select_id": 3, - "having_condition": "max_g > 25", - "filesort": { - "sort_key": "t2.e", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.e > 1" + "materialization": { + "query_block": { + "select_id": 2, + "having_condition": "v2.max_g < 100", + "temporary_table": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "v2.e < 5 and v2.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25", + "filesort": { + "sort_key": "t2.e", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.e > 1" + } } } } @@ -2956,27 +3018,29 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "d_tab.e < 5 and d_tab.e > 1", - "materialized": { - "query_block": { - "select_id": 3, - "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", - "filesort": { - "sort_key": "t2.f", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100 + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "d_tab.e < 5 and d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", + "filesort": { + "sort_key": "t2.f", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100 + } } } } @@ -3107,27 +3171,29 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "d_tab.e < 5 and d_tab.e > 1", - "materialized": { - "query_block": { - "select_id": 3, - "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", - "filesort": { - "sort_key": "t2.f", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100 + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "d_tab.e < 5 and d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", + "filesort": { + "sort_key": "t2.f", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100 + } } } } @@ -3259,27 +3325,29 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "temporary_table": { - "table": { - "table_name": "", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "d_tab.e < 5 and d_tab.e > 1", - "materialized": { - "query_block": { - "select_id": 3, - "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", - "filesort": { - "sort_key": "t2.f", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100 + "materialization": { + "query_block": { + "select_id": 2, + "temporary_table": { + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "d_tab.e < 5 and d_tab.e > 1", + "materialized": { + "query_block": { + "select_id": 3, + "having_condition": "max_g > 25 and t2.e < 5 and t2.e > 1", + "filesort": { + "sort_key": "t2.f", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100 + } } } } @@ -3418,16 +3486,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "having_condition": "t2.f < 5", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e > 1 and t2.e < 5" + "materialization": { + "query_block": { + "select_id": 3, + "having_condition": "t2.f < 5", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e > 1 and t2.e < 5" + } } } } @@ -3587,16 +3657,18 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 3, - "having_condition": "t2.f < 5", - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e > 1 and t2.e < 5" + "materialization": { + "query_block": { + "select_id": 3, + "having_condition": "t2.f < 5", + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e > 1 and t2.e < 5" + } } } } @@ -3684,21 +3756,23 @@ EXPLAIN "filtered": 100, "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "window_functions_computation": { - "sorts": { - "filesort": { - "sort_key": "t2.f" - } - }, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.f > 1" + "materialization": { + "query_block": { + "select_id": 2, + "window_functions_computation": { + "sorts": { + "filesort": { + "sort_key": "t2.f" + } + }, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.f > 1" + } } } } @@ -3777,21 +3851,23 @@ EXPLAIN "attached_condition": "t1.c = ``.`CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT)`", "materialized": { "unique": 1, - "query_block": { - "select_id": 2, - "window_functions_computation": { - "sorts": { - "filesort": { - "sort_key": "t2.f" - } - }, - "temporary_table": { - "table": { - "table_name": "t2", - "access_type": "ALL", - "rows": 12, - "filtered": 100, - "attached_condition": "t2.e < 5 and t2.f > 1" + "materialization": { + "query_block": { + "select_id": 2, + "window_functions_computation": { + "sorts": { + "filesort": { + "sort_key": "t2.f" + } + }, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 12, + "filtered": 100, + "attached_condition": "t2.e < 5 and t2.f > 1" + } } } } diff --git a/mysql-test/main/subselect_mat_analyze_json.result b/mysql-test/main/subselect_mat_analyze_json.result new file mode 100644 index 00000000000..454204edbd1 --- /dev/null +++ b/mysql-test/main/subselect_mat_analyze_json.result @@ -0,0 +1,945 @@ +set @save_optimizer_switch=@@optimizer_switch; +create table t1 (a int); +create table t2 (b int); +insert into t1 values (null), (1), (2), (3); +insert into t2 values (3), (4); +set @@optimizer_switch = "materialization=on,in_to_exists=off,semijoin=off"; +explain format=json select * from t1 where a in (select b from t2); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 4, + "filtered": 100, + "attached_condition": "(t1.a,t1.a in (subquery#2))" + }, + "subqueries": [ + { + "materialization": { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 2, + "filtered": 100 + } + } + } + } + ] + } +} +# "Complete match" execution strategy +analyze format=json select * from t1 where a in (select b from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 25, + "attached_condition": "(t1.a,t1.a in (subquery#2))" + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup", + "r_loops": 3, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +# "Partial match" is used due to NOT IN +# Force rowid-merge partial partial matching +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=off"; +analyze format=json select * from t1 where a not in (select b from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 50, + "attached_condition": "!(t1.a,t1.a in (subquery#2))" + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;array merge for partial match", + "r_loops": 4, + "r_index_lookups": 3, + "r_partial_matches": 1, + "r_partial_match_buffer_size": "REPLACED", + "r_partial_match_array_sizes": ["2"], + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +# Force table scan partial matching +set @@optimizer_switch="partial_match_rowid_merge=off,partial_match_table_scan=on"; +analyze format=json select * from t1 where a not in (select b from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 50, + "attached_condition": "!(t1.a,t1.a in (subquery#2))" + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 4, + "r_index_lookups": 3, + "r_partial_matches": 1, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +# Subselect in GROUP BY +analyze format=json select a from t1 group by a in (select b from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "filesort": { + "sort_key": "(t1.a,t1.a in (subquery#2))", + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "r_used_priority_queue": false, + "r_output_rows": 3, + "r_buffer_size": "REPLACED", + "r_sort_mode": "sort_key,rowid", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 4, + "r_index_lookups": 3, + "r_partial_matches": 1, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } + } + } +} +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=off"; +analyze format=json select a from t1 group by a not in (select b from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "filesort": { + "sort_key": "!(t1.a,t1.a in (subquery#2))", + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "r_used_priority_queue": false, + "r_output_rows": 3, + "r_buffer_size": "REPLACED", + "r_sort_mode": "sort_key,rowid", + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;array merge for partial match", + "r_loops": 4, + "r_index_lookups": 3, + "r_partial_matches": 1, + "r_partial_match_buffer_size": "REPLACED", + "r_partial_match_array_sizes": ["2"], + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } + } + } +} +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=on"; +# Subselect in ORDER BY +analyze format=json select a from t1 order by a in (select b from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "read_sorted_file": { + "r_rows": 4, + "filesort": { + "sort_key": "(t1.a,t1.a in (subquery#2))", + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "r_used_priority_queue": false, + "r_output_rows": 4, + "r_buffer_size": "REPLACED", + "r_sort_mode": "sort_key,addon_fields", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 4, + "r_index_lookups": 3, + "r_partial_matches": 1, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +# Subselect in HAVING +analyze format=json select a from t1 having a not in (select b from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "having_condition": "!(t1.a,t1.a in (subquery#2))", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 4, + "r_index_lookups": 3, + "r_partial_matches": 1, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +# Nested IN +analyze format=json select a from t1 where a in (select a from t1 where a in (select b from t2)); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 25, + "attached_condition": "(t1.a,t1.a in (subquery#2))" + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup", + "r_loops": 3, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 25, + "attached_condition": "(t1.a,t1.a in (subquery#3))" + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup", + "r_loops": 3, + "query_block": { + "select_id": 3, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } + } + } + ] + } +} +create table t3 (c int); +insert into t3 (c) values (3), (null), (4); +# Subquery in ON-clause of outer join +analyze format=json select a from t1 left join t2 on a not in (select c from t3); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "const_condition": "1", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "block-nl-join": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "buffer_type": "flat", + "buffer_size": "87", + "join_type": "BNL", + "attached_condition": "trigcond(trigcond(!(t1.a,t1.a in (subquery#2))))", + "r_filtered": 50, + "r_unpack_time_ms": "REPLACED" + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 4, + "r_index_lookups": 3, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t3", + "access_type": "ALL", + "r_loops": 1, + "rows": 3, + "r_rows": 3, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +analyze format=json +select (b, b + 1, b + 2) not in +(select count(distinct a), a + 1, a + 2 from t1 group by a + 1, a + 2) +from t2; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 2, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 2, + "r_index_lookups": 2, + "r_partial_matches": 2, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "read_sorted_file": { + "r_rows": 4, + "filesort": { + "sort_key": "t1.a + 1, t1.a + 2", + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "r_used_priority_queue": false, + "r_output_rows": 4, + "r_buffer_size": "REPLACED", + "r_sort_mode": "sort_key,addon_fields", + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + } + } + ] + } +} +drop table t1, t2, t3; +# +# Tables with more than one column +# +create table t1 (a1 char(1), a2 char(1)); +insert into t1 values (null, 'b'); +create table t2 (b1 char(1), b2 char(2)); +insert into t2 values ('a','b'), ('c', 'd'), (null, 'e'), ('f', 'g'); +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=off"; +explain format=json select * from t1 where (a1, a2) not in (select b1, b2 from t2); +EXPLAIN +{ + "query_block": { + "select_id": 1, + "const_condition": "!((NULL,'b'),(NULL,'b') in (subquery#2))", + "table": { + "table_name": "t1", + "access_type": "system", + "rows": 1, + "filtered": 100 + }, + "subqueries": [ + { + "materialization": { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100 + } + } + } + } + ] + } +} +analyze format=json select * from t1 where (a1, a2) not in (select b1, b2 from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "const_condition": "!((NULL,'b'),(NULL,'b') in (subquery#2))", + "table": { + "table_name": "t1", + "access_type": "system", + "r_loops": 0, + "rows": 1, + "r_rows": null, + "filtered": 100, + "r_filtered": null + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;array merge for partial match", + "r_loops": 1, + "r_partial_matches": 1, + "r_partial_match_buffer_size": "REPLACED", + "r_partial_match_array_sizes": ["4", "3"], + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +set @@optimizer_switch="partial_match_rowid_merge=off,partial_match_table_scan=on"; +analyze format=json select * from t1 where (a1, a2) not in (select b1, b2 from t2); +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "const_condition": "!((NULL,'b'),(NULL,'b') in (subquery#2))", + "table": { + "table_name": "t1", + "access_type": "system", + "r_loops": 0, + "rows": 1, + "r_rows": null, + "filtered": 100, + "r_filtered": null + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 1, + "r_partial_matches": 1, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +# Subquery in SELECT list +explain format=json select t1.*, (a1, a2) in (select * from t2) as in_res from t1; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "system", + "rows": 1, + "filtered": 100 + }, + "subqueries": [ + { + "materialization": { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 4, + "filtered": 100 + } + } + } + } + ] + } +} +analyze format=json select t1.*, (a1, a2) in (select * from t2) as in_res from t1; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "system", + "r_loops": 0, + "rows": 1, + "r_rows": null, + "filtered": 100, + "r_filtered": null + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 1, + "r_partial_matches": 1, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +analyze format=json select t1.*, (a1, a2) not in (select * from t2) as in_res from t1; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "system", + "r_loops": 0, + "rows": 1, + "r_rows": null, + "filtered": 100, + "r_filtered": null + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;full scan for partial match", + "r_loops": 1, + "r_partial_matches": 1, + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=off"; +analyze format=json select t1.*, (a1, a2) in (select * from t2) as in_res from t1; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "system", + "r_loops": 0, + "rows": 1, + "r_rows": null, + "filtered": 100, + "r_filtered": null + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;array merge for partial match", + "r_loops": 1, + "r_partial_matches": 1, + "r_partial_match_buffer_size": "REPLACED", + "r_partial_match_array_sizes": ["4", "3"], + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +analyze format=json select t1.*, (a1, a2) not in (select * from t2) as in_res from t1; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t1", + "access_type": "system", + "r_loops": 0, + "rows": 1, + "r_rows": null, + "filtered": 100, + "r_filtered": null + }, + "subqueries": [ + { + "materialization": { + "r_strategy": "index_lookup;array merge for partial match", + "r_loops": 1, + "r_partial_matches": 1, + "r_partial_match_buffer_size": "REPLACED", + "r_partial_match_array_sizes": ["4", "3"], + "query_block": { + "select_id": 2, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 1, + "rows": 4, + "r_rows": 4, + "r_table_time_ms": "REPLACED", + "r_other_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } + ] + } +} +drop table t1,t2; +set @@optimizer_switch=@save_optimizer_switch; diff --git a/mysql-test/main/subselect_mat_analyze_json.test b/mysql-test/main/subselect_mat_analyze_json.test new file mode 100644 index 00000000000..d949b9523bd --- /dev/null +++ b/mysql-test/main/subselect_mat_analyze_json.test @@ -0,0 +1,99 @@ +set @save_optimizer_switch=@@optimizer_switch; + +create table t1 (a int); +create table t2 (b int); +insert into t1 values (null), (1), (2), (3); +insert into t2 values (3), (4); + +set @@optimizer_switch = "materialization=on,in_to_exists=off,semijoin=off"; + +explain format=json select * from t1 where a in (select b from t2); +--echo # "Complete match" execution strategy +--source include/analyze-format.inc +analyze format=json select * from t1 where a in (select b from t2); + +--echo # "Partial match" is used due to NOT IN +--echo # Force rowid-merge partial partial matching +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=off"; +--source include/analyze-format.inc +analyze format=json select * from t1 where a not in (select b from t2); + +--echo # Force table scan partial matching +set @@optimizer_switch="partial_match_rowid_merge=off,partial_match_table_scan=on"; +--source include/analyze-format.inc +analyze format=json select * from t1 where a not in (select b from t2); + +--echo # Subselect in GROUP BY +--source include/analyze-format.inc +analyze format=json select a from t1 group by a in (select b from t2); + +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=off"; +--source include/analyze-format.inc +analyze format=json select a from t1 group by a not in (select b from t2); + +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=on"; +--echo # Subselect in ORDER BY +--source include/analyze-format.inc +analyze format=json select a from t1 order by a in (select b from t2); + +--echo # Subselect in HAVING +--source include/analyze-format.inc +analyze format=json select a from t1 having a not in (select b from t2); + +--echo # Nested IN +--source include/analyze-format.inc +analyze format=json select a from t1 where a in (select a from t1 where a in (select b from t2)); + +create table t3 (c int); +insert into t3 (c) values (3), (null), (4); + +--echo # Subquery in ON-clause of outer join +--source include/analyze-format.inc +analyze format=json select a from t1 left join t2 on a not in (select c from t3); + +--source include/analyze-format.inc +analyze format=json +select (b, b + 1, b + 2) not in + (select count(distinct a), a + 1, a + 2 from t1 group by a + 1, a + 2) +from t2; + +drop table t1, t2, t3; + + +--echo # +--echo # Tables with more than one column +--echo # +create table t1 (a1 char(1), a2 char(1)); +insert into t1 values (null, 'b'); +create table t2 (b1 char(1), b2 char(2)); +insert into t2 values ('a','b'), ('c', 'd'), (null, 'e'), ('f', 'g'); + +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=off"; +explain format=json select * from t1 where (a1, a2) not in (select b1, b2 from t2); +--source include/analyze-format.inc +analyze format=json select * from t1 where (a1, a2) not in (select b1, b2 from t2); + +set @@optimizer_switch="partial_match_rowid_merge=off,partial_match_table_scan=on"; +--source include/analyze-format.inc +analyze format=json select * from t1 where (a1, a2) not in (select b1, b2 from t2); + +--echo # Subquery in SELECT list +explain format=json select t1.*, (a1, a2) in (select * from t2) as in_res from t1; + +--source include/analyze-format.inc +analyze format=json select t1.*, (a1, a2) in (select * from t2) as in_res from t1; + +--source include/analyze-format.inc +analyze format=json select t1.*, (a1, a2) not in (select * from t2) as in_res from t1; + +set @@optimizer_switch="partial_match_rowid_merge=on,partial_match_table_scan=off"; +--source include/analyze-format.inc +analyze format=json select t1.*, (a1, a2) in (select * from t2) as in_res from t1; + +--source include/analyze-format.inc +analyze format=json select t1.*, (a1, a2) not in (select * from t2) as in_res from t1; + +drop table t1,t2; + + +set @@optimizer_switch=@save_optimizer_switch; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8ff9850e1b3..7f6e0fbfafc 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -42,6 +42,7 @@ #include "sql_parse.h" // check_stack_overrun #include "sql_cte.h" #include "sql_test.h" +#include "my_json_writer.h" double get_post_group_estimate(JOIN* join, double join_op_rows); @@ -192,6 +193,7 @@ void Item_in_subselect::cleanup() in_strategy&= ~SUBS_STRATEGY_CHOSEN; */ first_execution= TRUE; + materialization_tracker= NULL; pushed_cond_guards= NULL; Item_subselect::cleanup(); DBUG_VOID_RETURN; @@ -1602,6 +1604,7 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, st_select_lex *select_lex): Item_exists_subselect(thd), left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED), + materialization_tracker(NULL), pushed_cond_guards(NULL), do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE), @@ -3648,6 +3651,26 @@ bool Item_in_subselect::init_cond_guards() return FALSE; } +/** + Initialize the tracker which will be used to provide information for + the output of EXPLAIN and ANALYZE +*/ +void Item_in_subselect::init_subq_materialization_tracker(THD *thd) +{ + if (test_strategy(SUBS_MATERIALIZATION | SUBS_PARTIAL_MATCH_ROWID_MERGE | + SUBS_PARTIAL_MATCH_TABLE_SCAN)) + { + Explain_query *qw= thd->lex->explain; + DBUG_ASSERT(qw); + Explain_node *node= qw->get_node(unit->first_select()->select_number); + if (!node) + return; + node->subq_materialization= new(qw->mem_root) + Explain_subq_materialization(qw->mem_root); + materialization_tracker= node->subq_materialization->get_tracker(); + } +} + bool Item_allany_subselect::select_transformer(JOIN *join) @@ -4245,11 +4268,13 @@ int subselect_uniquesubquery_engine::exec() empty_result_set= TRUE; table->status= 0; Item_in_subselect *in_subs= item->get_IN_subquery(); + Subq_materialization_tracker *tracker= in_subs->get_materialization_tracker(); DBUG_ASSERT(in_subs); if (!tab->preread_init_done && tab->preread_init()) DBUG_RETURN(1); - + if (tracker) + tracker->increment_loops_count(); if (in_subs->left_expr_has_null()) { /* @@ -5002,6 +5027,9 @@ subselect_hash_sj_engine::choose_partial_match_strategy( partial_match_key_parts_arg); if (pm_buff_size > thd->variables.rowid_merge_buff_size) strategy= PARTIAL_MATCH_SCAN; + else + item->get_IN_subquery()->get_materialization_tracker()-> + report_partial_match_buffer_size(pm_buff_size); } } @@ -5777,6 +5805,7 @@ int subselect_hash_sj_engine::exec() } } + item_in->get_materialization_tracker()->report_exec_strategy(strategy); if (pm_engine) lookup_engine= pm_engine; item_in->change_engine(lookup_engine); @@ -6247,6 +6276,9 @@ int subselect_partial_match_engine::exec() DBUG_ASSERT(!(item_in->left_expr_has_null() && item_in->is_top_level_item())); + Subq_materialization_tracker *tracker= item_in->get_materialization_tracker(); + tracker->increment_loops_count(); + if (!item_in->left_expr_has_null()) { /* Try to find a matching row by index lookup. */ @@ -6260,6 +6292,7 @@ int subselect_partial_match_engine::exec() else { /* Search for a complete match. */ + tracker->increment_index_lookups(); if ((lookup_res= lookup_engine->index_lookup())) { /* An error occurred during lookup(). */ @@ -6304,6 +6337,7 @@ int subselect_partial_match_engine::exec() if (tmp_table->file->inited) tmp_table->file->ha_index_end(); + tracker->increment_partial_matches(); if (partial_match()) { /* The result of IN is UNKNOWN. */ @@ -6510,6 +6544,8 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts, 0, 0)) return TRUE; + item->get_IN_subquery()->get_materialization_tracker()-> + report_partial_merge_keys(merge_keys, merge_keys_count); return FALSE; } @@ -6966,3 +7002,12 @@ void Item_subselect::init_expr_cache_tracker(THD *thd) DBUG_ASSERT(expr_cache->type() == Item::EXPR_CACHE_ITEM); node->cache_tracker= ((Item_cache_wrapper *)expr_cache)->init_tracker(qw->mem_root); } + + +void Subq_materialization_tracker::report_partial_merge_keys( + Ordered_key **merge_keys, uint merge_keys_count) +{ + partial_match_array_sizes.resize(merge_keys_count, 0); + for (uint i= 0; i < merge_keys_count; i++) + partial_match_array_sizes[i]= merge_keys[i]->get_key_buff_elements(); +} diff --git a/sql/item_subselect.h b/sql/item_subselect.h index c1b531dc361..f976d905951 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -18,6 +18,7 @@ /* subselect Item */ +#include "item.h" #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif @@ -43,6 +44,8 @@ typedef class st_select_lex SELECT_LEX; */ typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); class Cached_item; +class Subq_materialization_tracker; +class Explain_subq_materialization; /* base class for subselects */ @@ -501,6 +504,8 @@ protected: bool was_null; /* A bitmap of possible execution strategies for an IN predicate. */ uchar in_strategy; + /* Tracker collecting execution parameters of a materialized subquery */ + Subq_materialization_tracker *materialization_tracker; protected: /* Used to trigger on/off conditions that were pushed down to subselect */ bool *pushed_cond_guards; @@ -525,6 +530,7 @@ protected: left_expr could later be changed to something on the execution arena. */ Item *left_expr_orig; + public: /* Priority of this predicate in the convert-to-semi-join-nest process. */ int sj_convert_priority; @@ -626,7 +632,7 @@ public: Item_in_subselect(THD *thd_arg, Item * left_expr, st_select_lex *select_lex); Item_in_subselect(THD *thd_arg): Item_exists_subselect(thd_arg), left_expr_cache(0), first_execution(TRUE), - in_strategy(SUBS_NOT_TRANSFORMED), + in_strategy(SUBS_NOT_TRANSFORMED), materialization_tracker(NULL), pushed_cond_guards(NULL), func(NULL), do_not_convert_to_sj(FALSE), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), upper_item(0), converted_from_in_predicate(FALSE) {} @@ -778,6 +784,9 @@ public: { return left_expr; } inline Item* left_exp_orig() const { return left_expr_orig; } + void init_subq_materialization_tracker(THD *thd); + Subq_materialization_tracker *get_materialization_tracker() const + { return materialization_tracker; } friend class Item_ref_null_helper; friend class Item_is_not_null_test; @@ -1159,6 +1168,15 @@ public: select_result_interceptor *result, bool temp= FALSE) override; bool no_tables() const override;//=>base class + /* Possible execution strategies that can be used to compute hash semi-join.*/ + enum exec_strategy { + UNDEFINED= 0, + COMPLETE_MATCH, /* Use regular index lookups. */ + PARTIAL_MATCH, /* Use some partial matching strategy. */ + PARTIAL_MATCH_MERGE, /* Use partial matching through index merging. */ + PARTIAL_MATCH_SCAN, /* Use partial matching through table scan. */ + IMPOSSIBLE /* Subquery materialization is not applicable. */ + }; protected: /* The engine used to compute the IN predicate. */ @@ -1170,15 +1188,6 @@ protected: uint count_partial_match_columns; uint count_null_only_columns; uint count_columns_with_nulls; - /* Possible execution strategies that can be used to compute hash semi-join.*/ - enum exec_strategy { - UNDEFINED, - COMPLETE_MATCH, /* Use regular index lookups. */ - PARTIAL_MATCH, /* Use some partial matching strategy. */ - PARTIAL_MATCH_MERGE, /* Use partial matching through index merging. */ - PARTIAL_MATCH_SCAN, /* Use partial matching through table scan. */ - IMPOSSIBLE /* Subquery materialization is not applicable. */ - }; /* The chosen execution strategy. Computed after materialization. */ exec_strategy strategy; exec_strategy get_strategy_using_schema(); @@ -1311,6 +1320,7 @@ public: rownum_t get_max_null_row() { return max_null_row; } MY_BITMAP * get_null_key() { return &null_key; } ha_rows get_null_count() { return null_count; } + ha_rows get_key_buff_elements() { return key_buff_elements; } /* Get the search key element that corresponds to the i-th key part of this index. @@ -1548,4 +1558,93 @@ public: void cleanup() override; enum_engine_type engine_type() override { return TABLE_SCAN_ENGINE; } }; + +/** + @brief Subquery materialization tracker + + @details + Used to track various parameters of the materialized subquery execution, + such as the execution strategy, sizes of buffers employed, etc +*/ +class Subq_materialization_tracker +{ +public: + using Strategy = subselect_hash_sj_engine::exec_strategy; + + Subq_materialization_tracker(MEM_ROOT *mem_root) + : exec_strategy(Strategy::UNDEFINED), + partial_match_buffer_size(0), + partial_match_array_sizes(mem_root), + loops_count(0), + index_lookups_count(0), + partial_matches_count(0) + {} + + void report_partial_merge_keys(Ordered_key **merge_keys, + uint merge_keys_count); + + void report_exec_strategy(Strategy es) + { + exec_strategy= es; + } + + void report_partial_match_buffer_size(longlong sz) + { + partial_match_buffer_size= sz; + } + + void increment_loops_count() + { + loops_count++; + } + + void increment_index_lookups() + { + index_lookups_count++; + } + + void increment_partial_matches() + { + partial_matches_count++; + } + + void print_json_members(Json_writer *writer) const; +private: + Strategy exec_strategy; + ulonglong partial_match_buffer_size; + Dynamic_array partial_match_array_sizes; + + /* Number of times subquery predicate was evaluated */ + ulonglong loops_count; + + /* + Number of times we made a lookup in the materialized temptable + (we do this when all parts of left_expr are not NULLs) + */ + ulonglong index_lookups_count; + + /* + Number of times we had to check for a partial match (either by + scanning the materialized subquery or by doing a merge) + */ + ulonglong partial_matches_count; + + const char *get_exec_strategy() const + { + switch (exec_strategy) + { + case Strategy::UNDEFINED: + return "undefined"; + case Strategy::COMPLETE_MATCH: + return "index_lookup"; + case Strategy::PARTIAL_MATCH_MERGE: + return "index_lookup;array merge for partial match"; + case Strategy::PARTIAL_MATCH_SCAN: + return "index_lookup;full scan for partial match"; + default: + return "unsupported"; + } + } +}; + #endif /* ITEM_SUBSELECT_INCLUDED */ diff --git a/sql/sql_array.h b/sql/sql_array.h index b6de1b18d78..bc4afa8906f 100644 --- a/sql/sql_array.h +++ b/sql/sql_array.h @@ -140,12 +140,24 @@ public: DBUG_ASSERT(idx < array.elements); return *(((Elem*)array.buffer) + idx); } + /// Const variant of at(), which cannot change data const Elem& at(size_t idx) const { return *(((Elem*)array.buffer) + idx); } + Elem& operator[](size_t idx) + { + return at(idx); + } + + /// Const variant of operator[] + const Elem& operator[](size_t idx) const + { + return at(idx); + } + /// @returns pointer to first element Elem *front() { diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 3d97645d212..bfd73074f76 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -24,6 +24,7 @@ #include "my_json_writer.h" #include "opt_range.h" #include "sql_expression_cache.h" +#include "item_subselect.h" const char * STR_DELETING_ALL_ROWS= "Deleting all rows"; const char * STR_IMPOSSIBLE_WHERE= "Impossible WHERE"; @@ -782,6 +783,18 @@ bool Explain_node::print_explain_json_cache(Json_writer *writer, } +bool Explain_node::print_explain_json_subq_materialization(Json_writer *writer, + bool is_analyze) +{ + if (subq_materialization) + { + subq_materialization->print_explain_json(writer, is_analyze); + return true; + } + return false; +} + + Explain_basic_join::~Explain_basic_join() { if (join_tabs) @@ -929,6 +942,8 @@ void Explain_select::print_explain_json(Explain_query *query, Json_writer_nesting_guard guard(writer); bool started_cache= print_explain_json_cache(writer, is_analyze); + bool started_subq_mat= print_explain_json_subq_materialization(writer, + is_analyze); if (message || select_type == pushed_derived_text || @@ -1032,6 +1047,8 @@ void Explain_select::print_explain_json(Explain_query *query, writer->end_object(); } + if (started_subq_mat) + writer->end_object(); if (started_cache) writer->end_object(); } @@ -2693,3 +2710,41 @@ void Explain_range_checked_fer::print_json(Json_writer *writer, writer->end_object(); } } + + +void Explain_subq_materialization::print_explain_json(Json_writer *writer, + bool is_analyze) +{ + writer->add_member("materialization").start_object(); + if (is_analyze) + tracker.print_json_members(writer); +} + + +void Subq_materialization_tracker::print_json_members(Json_writer *writer) const +{ + writer->add_member("r_strategy").add_str(get_exec_strategy()); + if (loops_count) + writer->add_member("r_loops").add_ull(loops_count); + + if (index_lookups_count) + writer->add_member("r_index_lookups").add_ull(index_lookups_count); + + if (partial_matches_count) + writer->add_member("r_partial_matches").add_ull(partial_matches_count); + + if (partial_match_buffer_size) + { + writer->add_member("r_partial_match_buffer_size"). + add_size(partial_match_buffer_size); + } + + if (partial_match_array_sizes.elements()) + { + writer->add_member("r_partial_match_array_sizes").start_array(); + for(size_t i= 0; i < partial_match_array_sizes.elements(); i++) + writer->add_ull(partial_match_array_sizes[i]); + writer->end_array(); + } +} + diff --git a/sql/sql_explain.h b/sql/sql_explain.h index e7b054ed75b..cf960f75da4 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -86,6 +86,7 @@ class Explain_node : public Sql_alloc public: Explain_node(MEM_ROOT *root) : cache_tracker(NULL), + subq_materialization(NULL), connection_type(EXPLAIN_NODE_OTHER), children(root) {} @@ -115,6 +116,12 @@ public: */ Expression_cache_tracker* cache_tracker; + /** + If not NULL, this node is a SELECT (or UNION) in a materialized + IN-subquery. + */ + Explain_subq_materialization* subq_materialization; + /* How this node is connected to its parent. (NOTE: EXPLAIN_NODE_NON_MERGED_SJ is set very late currently) @@ -143,6 +150,8 @@ public: void print_explain_json_for_children(Explain_query *query, Json_writer *writer, bool is_analyze); bool print_explain_json_cache(Json_writer *writer, bool is_analyze); + bool print_explain_json_subq_materialization(Json_writer *writer, + bool is_analyze); virtual ~Explain_node() = default; }; @@ -1003,4 +1012,26 @@ public: }; +/* + EXPLAIN data structure for subquery materialization. + + All decisions are made at execution time so here we just store the tracker + that has all the info. +*/ + +class Explain_subq_materialization : public Sql_alloc +{ +public: + Explain_subq_materialization(MEM_ROOT *mem_root) + : tracker(mem_root) + {} + + Subq_materialization_tracker *get_tracker() { return &tracker; } + + void print_explain_json(Json_writer *writer, bool is_analyze); + +private: + Subq_materialization_tracker tracker; +}; + #endif //SQL_EXPLAIN_INCLUDED diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2ab1736891c..b86ffed8619 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1729,6 +1729,11 @@ bool JOIN::build_explain() curr_tab->tracker= tmp->get_using_temporary_read_tracker(); } } + if (is_in_subquery()) + { + Item_in_subselect *subq= unit->item->get_IN_subquery(); + subq->init_subq_materialization_tracker(thd); + } DBUG_RETURN(0); }