diff --git a/mysql-test/main/mdev-38877.result b/mysql-test/main/mdev-38877.result new file mode 100644 index 0000000000000..a0b114f50ac4a --- /dev/null +++ b/mysql-test/main/mdev-38877.result @@ -0,0 +1,32 @@ +# +# MDEV-38877: Unnecessary filesort on derived table materialization +# when derived table is inherently sorted by the grouping columns +# +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; diff --git a/mysql-test/main/mdev-38877.test b/mysql-test/main/mdev-38877.test new file mode 100644 index 0000000000000..ae6699261937d --- /dev/null +++ b/mysql-test/main/mdev-38877.test @@ -0,0 +1,39 @@ +--source include/have_sequence.inc + +--echo # +--echo # MDEV-38877: Unnecessary filesort on derived table materialization +--echo # when derived table is inherently sorted by the grouping columns +--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; \ No newline at end of file diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b8fbbe2f62f58..652021d0d4ed0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7916,7 +7916,21 @@ bool sort_and_filter_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse, { if (!(use->used_tables & ~OUTER_REF_TABLE_BIT) && use->optimize != KEY_OPTIMIZE_REF_OR_NULL) - use->table->const_key_parts[use->key]|= use->keypart_map; + { + TABLE_LIST *derived_table= use->table->pos_in_table_list; + if (derived_table && derived_table->select_lex) + { + st_select_lex_unit *master_unit= + derived_table->select_lex->master_unit(); + if (master_unit) + derived_table= master_unit->derived; + } + // derived tables shouldn't treat outer + // references as constants + if (!(derived_table && derived_table->is_materialized_derived()) || + use->used_tables == 0) + use->table->const_key_parts[use->key]|= use->keypart_map; + } if (use->keypart != FT_KEYPART) { if (use->key == prev->key && use->table == prev->table) @@ -27562,7 +27576,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, *fatal_error= false; /* Check that we are always called with first non-const table */ DBUG_ASSERT(tab == tab->join->join_tab + tab->join->const_tables); - /* Sorting a single row can always be skipped */ if (tab->type == JT_EQ_REF || tab->type == JT_CONST ||