diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result index 8a03938837520..50a1e03ad7772 100644 --- a/mysql-test/main/derived_cond_pushdown.result +++ b/mysql-test/main/derived_cond_pushdown.result @@ -21164,7 +21164,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY ALL NULL NULL NULL NULL 7 100.00 2 DERIVED ALL NULL NULL NULL NULL 7 100.00 Using temporary; Using filesort 2 DERIVED a2 eq_ref PRIMARY PRIMARY 4 a1.f 1 100.00 Using index -4 DERIVED t1 index PRIMARY PRIMARY 4 NULL 7 100.00 Using index; Using temporary; Using filesort +4 DERIVED t1 index PRIMARY PRIMARY 4 NULL 7 100.00 Using index Warnings: Note 1003 /* select#1 */ select `s`.`f` AS `f`,`s`.`c` AS `c` from (/* select#2 */ select straight_join `a2`.`f` AS `f`,count(0) AS `c` from (/* select#4 */ select `test`.`t1`.`f` AS `f`,count(0) AS `c` from `test`.`t1` group by `test`.`t1`.`f`) `a1` join `test`.`t1` `a2` where `a2`.`f` = `a1`.`f` group by `a2`.`f`) `s` SELECT * FROM ( SELECT STRAIGHT_JOIN f, COUNT(*) as c FROM v1 GROUP BY f ) AS s; @@ -21994,7 +21994,7 @@ EXPLAIN "loops": 1, "rows": 1, "cost": "COST_REPLACED", - "filtered": 34.55045319, + "filtered": 5.050564766, "index_condition": "t2.t1_id between 200 and 100000 and t2.t1_id = t3.t1_id", "attached_condition": "t2.reporting_person = 1" } diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result index 6951da7371816..21a70709eef15 100644 --- a/mysql-test/main/derived_split_innodb.result +++ b/mysql-test/main/derived_split_innodb.result @@ -131,7 +131,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t const f2 NULL NULL NULL 0 Impossible ON condition 1 PRIMARY const key0,key1 NULL NULL NULL 0 Impossible ON condition 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 -2 DERIVED t2 ALL PRIMARY NULL NULL NULL 3 Using temporary; Using filesort +2 DERIVED t2 index PRIMARY PRIMARY 4 NULL 3 set statement optimizer_switch='split_materialized=off' for explain select t.f2 from t1 left join @@ -998,7 +998,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 1 PRIMARY t2 ref a a 5 test.t1.a 1 Using where; Using index 1 PRIMARY ref key0 key0 5 func 1 Using where -2 DERIVED t10 index grp_id grp_id 5 NULL 10000 Using index; Using temporary; Using filesort +2 DERIVED t10 index grp_id grp_id 5 NULL 10000 Using index drop table t1,t2, t10; drop view v1; # @@ -1258,7 +1258,7 @@ EXPLAIN "loops": 1, "rows": 1, "cost": "REPLACED", - "filtered": 100, + "filtered": 7.142857075, "index_condition": "t3.a < 1 and t3.b <=> t1.b and t3.b <=> t2.b and t3.a = t2.a" } } @@ -1376,4 +1376,36 @@ a b c d amount a b name a b description 0 NULL 0 NULL 10 0 NULL a 0 NULL gold drop table t1, t2, t3; # End of 11.4 tests +# +# MDEV-38877: Unnecessary filesort on derived table materialization +# +CREATE TABLE t1 ( +groups_20 int NOT NULL, +groups_20_2 int NOT NULL, +b int, +PRIMARY KEY (groups_20, groups_20_2) +); +CREATE TABLE t2 (a int, b int, index(a)); +INSERT INTO t1 SELECT seq/1000, seq+1, seq from seq_1_to_10000; +INSERT INTO t2 SELECT seq, seq from seq_1_to_1000; +ANALYZE TABLE t1, t2; +EXPLAIN +SELECT +a, +SUM(b) +FROM ( +SELECT +groups_20 +FROM t1 +GROUP BY groups_20 +HAVING COUNT(*) != 1000 +) DT +JOIN t2 ON a = groups_20 +GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 ALL a NULL NULL NULL 1000 Using where; Using temporary; Using filesort +1 PRIMARY ref key0 key0 4 test.t2.a 1 +2 DERIVED t1 index PRIMARY PRIMARY 8 NULL 10000 Using index +DROP TABLE t1, t2; +# End of 12.3 tests SET GLOBAL innodb_stats_persistent=@save_innodb_stats_persistent; diff --git a/mysql-test/main/derived_split_innodb.test b/mysql-test/main/derived_split_innodb.test index 207d5e084d4a2..d414c4106d239 100644 --- a/mysql-test/main/derived_split_innodb.test +++ b/mysql-test/main/derived_split_innodb.test @@ -811,4 +811,43 @@ drop table t1, t2, t3; --echo # End of 11.4 tests +--echo # +--echo # MDEV-38877: Unnecessary filesort on derived table materialization +--echo # + +CREATE TABLE t1 ( + groups_20 int NOT NULL, + groups_20_2 int NOT NULL, + b int, + PRIMARY KEY (groups_20, groups_20_2) +); + +CREATE TABLE t2 (a int, b int, index(a)); + +--disable_result_log +INSERT INTO t1 SELECT seq/1000, seq+1, seq from seq_1_to_10000; + +INSERT INTO t2 SELECT seq, seq from seq_1_to_1000; + +ANALYZE TABLE t1, t2; +--enable_result_log + +EXPLAIN +SELECT + a, + SUM(b) +FROM ( + SELECT + groups_20 + FROM t1 + GROUP BY groups_20 + HAVING COUNT(*) != 1000 +) DT +JOIN t2 ON a = groups_20 +GROUP BY a; + +DROP TABLE t1, t2; + +--echo # End of 12.3 tests + SET GLOBAL innodb_stats_persistent=@save_innodb_stats_persistent; diff --git a/mysql-test/main/opt_hints_split_materialized.result b/mysql-test/main/opt_hints_split_materialized.result index 798b3b53c7cd9..b1e656b3e606d 100644 --- a/mysql-test/main/opt_hints_split_materialized.result +++ b/mysql-test/main/opt_hints_split_materialized.result @@ -763,7 +763,7 @@ one_k T1, (select grp, count(*) from t1000 group by grp) TBL where TBL.grp=T1.a; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY T1 ALL NULL NULL NULL NULL 1000 Using where 1 PRIMARY ref key0 key0 5 test.T1.a 1 -2 DERIVED t1000 index grp grp 5 NULL 1000 Using index; Using temporary; Using filesort +2 DERIVED t1000 index grp grp 5 NULL 1000 Using index explain select /*+ SPLIT_MATERIALIZED(TBL) */ * from @@ -771,7 +771,7 @@ one_k T1, (select grp, count(*) from t1000 group by grp) TBL where TBL.grp=T1.a; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY ALL NULL NULL NULL NULL 100 1 PRIMARY T1 ALL NULL NULL NULL NULL 1000 Using where; Using join buffer (flat, BNL join) -2 DERIVED t1000 index grp grp 5 NULL 1000 Using index; Using temporary; Using filesort +2 DERIVED t1000 index grp grp 5 NULL 1000 Using index drop table one_k, t1000; # # end case 4 diff --git a/sql/opt_split.cc b/sql/opt_split.cc index 33a3369f0e519..e63f9dc5b2d37 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -890,7 +890,7 @@ void JOIN::add_keyuses_for_splitting() added_keyuse->validity_ref= &keyuse_ext->validity_var; } - if (sort_and_filter_keyuse(this, &keyuse, true)) + if (sort_and_filter_keyuse(this, &keyuse, true, true)) goto err; optimize_keyuse(this, &keyuse); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b8fbbe2f62f58..6c1b9569cde6f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7886,7 +7886,8 @@ static void remember_if_eq_ref_key(JOIN *join, KEYUSE *use) */ bool sort_and_filter_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse, - bool skip_unprefixed_keyparts) + bool skip_unprefixed_keyparts, + bool is_splitting) { THD *thd= join->thd; KEYUSE key_end, *prev, *save_pos, *use; @@ -7914,7 +7915,8 @@ bool sort_and_filter_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse, { if (!use->is_for_hash_join()) { - if (!(use->used_tables & ~OUTER_REF_TABLE_BIT) && + if (!is_splitting && + !(use->used_tables & ~OUTER_REF_TABLE_BIT) && use->optimize != KEY_OPTIMIZE_REF_OR_NULL) use->table->const_key_parts[use->key]|= use->keypart_map; if (use->keypart != FT_KEYPART) diff --git a/sql/sql_select.h b/sql/sql_select.h index 1b001494e2fa2..4960970b5028f 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -2674,7 +2674,8 @@ bool open_tmp_table(TABLE *table); void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List *tlist); void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array); bool sort_and_filter_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse, - bool skip_unprefixed_keyparts); + bool skip_unprefixed_keyparts, + bool is_splitting= false); struct TMPTABLE_COSTS {