summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-06-04 10:07:29 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2021-06-04 10:07:29 +0300
commit3c97097f11bf111b7b25378e0c05011849e57541 (patch)
tree6651c2ba0985109fa545932588dd4be35dd6866a
parent8426c7411bcd1c3efec6a65db98266b0cad5f62a (diff)
parentbab4348c6c1253f8d23f688f7ac083a4e902b701 (diff)
downloadmariadb-git-3c97097f11bf111b7b25378e0c05011849e57541.tar.gz
Merge 10.4 into 10.5
-rw-r--r--mysql-test/main/derived_cond_pushdown.result2
-rw-r--r--mysql-test/main/derived_split_innodb.result65
-rw-r--r--mysql-test/main/derived_split_innodb.test41
-rw-r--r--mysql-test/main/lock_kill.test4
-rw-r--r--sql/field.cc2
-rw-r--r--sql/opt_split.cc27
-rw-r--r--storage/innobase/include/srv0mon.h2
-rw-r--r--storage/innobase/page/page0cur.cc12
8 files changed, 141 insertions, 14 deletions
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 33b625a0f6d..016ca22af1b 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -16679,7 +16679,7 @@ EXPLAIN EXTENDED
SELECT * FROM v1 JOIN v2 ON v1.f = v2.f;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
-3 LATERAL DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+3 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 /* select#1 */ select NULL AS `f`,`v2`.`f` AS `f` from `test`.`t1` `a` straight_join `test`.`t1` `b` join `test`.`v2` where 0
DROP VIEW v1,v2;
diff --git a/mysql-test/main/derived_split_innodb.result b/mysql-test/main/derived_split_innodb.result
index 55ace91507e..9edf9a1f2ae 100644
--- a/mysql-test/main/derived_split_innodb.result
+++ b/mysql-test/main/derived_split_innodb.result
@@ -176,3 +176,68 @@ id select_type table type possible_keys key key_len ref rows Extra
3 LATERAL DERIVED t1 ref a,a_2 a 5 test.t1.a 1 Using where; Using temporary; Using filesort
3 LATERAL DERIVED t2 ref c c 5 test.t1.b 1 Using index
DROP TABLE t1, t2;
+#
+# Bug mdev-25714: usage non-splitting covering index is cheaper than
+# usage of the best splitting index for one group
+#
+create table t1 (
+id int not null, itemid int not null, index idx (itemid)
+) engine=innodb;
+insert into t1 values (1, 2), (2,2), (4,2), (4,2), (0,3), (3,3);
+create table t2 (id int not null) engine=innodb;
+insert into t2 values (2);
+create table t3 (
+id int not null, itemid int not null, userid int not null, primary key (id),
+index idx1 (userid, itemid), index idx2 (itemid)
+) engine innodb;
+insert into t3 values (1,1,1), (2,1,1), (3,2,1), (4,2,1), (5,3,1);
+set use_stat_tables='never';
+set optimizer_use_condition_selectivity=1;
+analyze table t1,t2,t3;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+test.t3 analyze status OK
+set optimizer_switch='split_materialized=on';
+explain select t1.id, t1.itemid, dt.id, t2.id
+from t1,
+(select itemid, max(id) as id from t3 where userid = 1 group by itemid) dt,
+t2
+where t1.id = dt.id and t1.itemid = dt.itemid and t2.id=t1.itemid;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 1
+1 PRIMARY <derived2> ref key1 key1 4 test.t2.id 2
+1 PRIMARY t1 ALL idx NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
+2 DERIVED t3 ref idx1,idx2 idx1 4 const 5 Using where; Using index
+select t1.id, t1.itemid, dt.id, t2.id
+from t1,
+(select itemid, max(id) as id from t3 where userid = 1 group by itemid) dt,
+t2
+where t1.id = dt.id and t1.itemid = dt.itemid and t2.id=t1.itemid;
+id itemid id id
+4 2 4 2
+4 2 4 2
+set optimizer_switch='split_materialized=off';
+explain select t1.id, t1.itemid, dt.id, t2.id
+from t1,
+(select itemid, max(id) as id from t3 where userid = 1 group by itemid) dt,
+t2
+where t1.id = dt.id and t1.itemid = dt.itemid and t2.id=t1.itemid;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 1
+1 PRIMARY <derived2> ref key1 key1 4 test.t2.id 2
+1 PRIMARY t1 ALL idx NULL NULL NULL 6 Using where; Using join buffer (flat, BNL join)
+2 DERIVED t3 ref idx1 idx1 4 const 5 Using where; Using index
+select t1.id, t1.itemid, dt.id, t2.id
+from t1,
+(select itemid, max(id) as id from t3 where userid = 1 group by itemid) dt,
+t2
+where t1.id = dt.id and t1.itemid = dt.itemid and t2.id=t1.itemid;
+id itemid id id
+4 2 4 2
+4 2 4 2
+drop table t1,t2,t3;
+set optimizer_switch='split_materialized=default';
+set use_stat_tables=default;
+set optimizer_use_condition_selectivity=default;
+# End of 10.3 tests
diff --git a/mysql-test/main/derived_split_innodb.test b/mysql-test/main/derived_split_innodb.test
index 10fc3f93190..bee9ef497b6 100644
--- a/mysql-test/main/derived_split_innodb.test
+++ b/mysql-test/main/derived_split_innodb.test
@@ -152,3 +152,44 @@ eval set statement optimizer_switch='split_materialized=on' for $query;
DROP TABLE t1, t2;
+--echo #
+--echo # Bug mdev-25714: usage non-splitting covering index is cheaper than
+--echo # usage of the best splitting index for one group
+--echo #
+
+create table t1 (
+ id int not null, itemid int not null, index idx (itemid)
+) engine=innodb;
+insert into t1 values (1, 2), (2,2), (4,2), (4,2), (0,3), (3,3);
+create table t2 (id int not null) engine=innodb;
+insert into t2 values (2);
+create table t3 (
+ id int not null, itemid int not null, userid int not null, primary key (id),
+ index idx1 (userid, itemid), index idx2 (itemid)
+) engine innodb;
+insert into t3 values (1,1,1), (2,1,1), (3,2,1), (4,2,1), (5,3,1);
+set use_stat_tables='never';
+set optimizer_use_condition_selectivity=1;
+analyze table t1,t2,t3;
+
+let $q=
+select t1.id, t1.itemid, dt.id, t2.id
+ from t1,
+ (select itemid, max(id) as id from t3 where userid = 1 group by itemid) dt,
+ t2
+ where t1.id = dt.id and t1.itemid = dt.itemid and t2.id=t1.itemid;
+
+set optimizer_switch='split_materialized=on';
+eval explain $q;
+eval $q;
+
+set optimizer_switch='split_materialized=off';
+eval explain $q;
+eval $q;
+
+drop table t1,t2,t3;
+set optimizer_switch='split_materialized=default';
+set use_stat_tables=default;
+set optimizer_use_condition_selectivity=default;
+
+--echo # End of 10.3 tests
diff --git a/mysql-test/main/lock_kill.test b/mysql-test/main/lock_kill.test
index dfeebbc4f6a..2c1396e5ff3 100644
--- a/mysql-test/main/lock_kill.test
+++ b/mysql-test/main/lock_kill.test
@@ -17,7 +17,7 @@ LOCK TABLE t1 WRITE;
eval KILL $conid;
--enable_query_log
--connection con1
---error 0,2013,ER_CONNECTION_KILLED
+--error 0,2006,2013,ER_CONNECTION_KILLED
reap;
--connection default
--disconnect con1
@@ -35,7 +35,7 @@ LOCK TABLE t1 WRITE, t2 WRITE;
eval KILL $conid;
--enable_query_log
--connection con1
---error 0,2013,ER_CONNECTION_KILLED
+--error 0,2006,2013,ER_CONNECTION_KILLED
reap;
--connection default
--disconnect con1
diff --git a/sql/field.cc b/sql/field.cc
index f3deffccee5..ab4f6a96921 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -7857,7 +7857,7 @@ bool Field_varstring::send(Protocol *protocol)
#ifdef HAVE_MEM_CHECK
void Field_varstring::mark_unused_memory_as_defined()
{
- uint used_length= get_length();
+ uint used_length __attribute__((unused)) = get_length();
MEM_MAKE_DEFINED(get_data() + used_length, field_length - used_length);
}
#endif
diff --git a/sql/opt_split.cc b/sql/opt_split.cc
index 28a54838169..316919c4a81 100644
--- a/sql/opt_split.cc
+++ b/sql/opt_split.cc
@@ -958,11 +958,7 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(double record_count,
in the cache
*/
spl_plan= spl_opt_info->find_plan(best_table, best_key, best_key_parts);
- if (!spl_plan &&
- (spl_plan= (SplM_plan_info *) thd->alloc(sizeof(SplM_plan_info))) &&
- (spl_plan->best_positions=
- (POSITION *) thd->alloc(sizeof(POSITION) * join->table_count)) &&
- !spl_opt_info->plan_cache.push_back(spl_plan))
+ if (!spl_plan)
{
/*
The plan for the chosen key has not been found in the cache.
@@ -972,6 +968,27 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(double record_count,
reset_validity_vars_for_keyuses(best_key_keyuse_ext_start, best_table,
best_key, remaining_tables, true);
choose_plan(join, all_table_map & ~join->const_table_map);
+
+ /*
+ Check that the chosen plan is really a splitting plan.
+ If not or if there is not enough memory to save the plan in the cache
+ then just return with no splitting plan.
+ */
+ POSITION *first_non_const_pos= join->best_positions + join->const_tables;
+ TABLE *table= first_non_const_pos->table->table;
+ key_map spl_keys= table->keys_usable_for_splitting;
+ if (!(first_non_const_pos->key &&
+ spl_keys.is_set(first_non_const_pos->key->key)) ||
+ !(spl_plan= (SplM_plan_info *) thd->alloc(sizeof(SplM_plan_info))) ||
+ !(spl_plan->best_positions=
+ (POSITION *) thd->alloc(sizeof(POSITION) * join->table_count)) ||
+ spl_opt_info->plan_cache.push_back(spl_plan))
+ {
+ reset_validity_vars_for_keyuses(best_key_keyuse_ext_start, best_table,
+ best_key, remaining_tables, false);
+ return 0;
+ }
+
spl_plan->keyuse_ext_start= best_key_keyuse_ext_start;
spl_plan->table= best_table;
spl_plan->key= best_key;
diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h
index 77a90b0c84a..cbda9d06338 100644
--- a/storage/innobase/include/srv0mon.h
+++ b/storage/innobase/include/srv0mon.h
@@ -639,7 +639,7 @@ Use MONITOR_DEC if appropriate mutex protection exists.
#ifdef HAVE_MEM_CHECK
# define MONITOR_CHECK_DEFINED(value) do { \
- mon_type_t m = value; \
+ mon_type_t m __attribute__((unused))= value; \
MEM_CHECK_DEFINED(&m, sizeof m); \
} while (0)
#else /* HAVE_MEM_CHECK */
diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc
index f75d1a8be77..cc6b1797d61 100644
--- a/storage/innobase/page/page0cur.cc
+++ b/storage/innobase/page/page0cur.cc
@@ -1315,8 +1315,10 @@ page_cur_insert_rec_low(
#ifdef HAVE_MEM_CHECK
{
- const void *rec_start= rec - rec_offs_extra_size(offsets);
- ulint extra_size= rec_offs_extra_size(offsets) -
+ const void *rec_start __attribute__((unused))=
+ rec - rec_offs_extra_size(offsets);
+ ulint extra_size __attribute__((unused))=
+ rec_offs_extra_size(offsets) -
(page_is_comp(block->frame)
? REC_N_NEW_EXTRA_BYTES
: REC_N_OLD_EXTRA_BYTES);
@@ -1722,8 +1724,10 @@ page_cur_insert_rec_zip(
#ifdef HAVE_MEM_CHECK
{
- const void *rec_start= rec - rec_offs_extra_size(offsets);
- ulint extra_size= rec_offs_extra_size(offsets) - REC_N_NEW_EXTRA_BYTES;
+ const void *rec_start __attribute__((unused))=
+ rec - rec_offs_extra_size(offsets);
+ ulint extra_size __attribute__((unused))=
+ rec_offs_extra_size(offsets) - REC_N_NEW_EXTRA_BYTES;
/* All data bytes of the record must be valid. */
MEM_CHECK_DEFINED(rec, rec_offs_data_size(offsets));
/* The variable-length header must be valid. */