Commit 69e6a2bb authored by Sergey Petrunya's avatar Sergey Petrunya

MDEV-3798: EXPLAIN UPDATE/DELETE

- Update test results after last few csets
- Generate correct value for `possible_keys` column for single table UPDATE/DELETE.
parent fda46df6
...@@ -13,7 +13,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -13,7 +13,7 @@ id select_type table type possible_keys key key_len ref rows Extra
# DELETE without WHERE is a special case: # DELETE without WHERE is a special case:
explain delete from t0; explain delete from t0;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Deleting all rows 1 SIMPLE NULL NULL NULL NULL NULL NULL 8 Deleting all rows
create table t1 (a int, b int, filler char(100), key(a), key(b)); create table t1 (a int, b int, filler char(100), key(a), key(b));
insert into t1 insert into t1
select A.a+10*B.a + 10*C.a, A.a+10*B.a + 10*C.a, 'filler' select A.a+10*B.a + 10*C.a, A.a+10*B.a + 10*C.a, 'filler'
...@@ -65,10 +65,10 @@ select A.a+10*B.a + 10*C.a, A.a+10*B.a + 10*C.a, 'filler' ...@@ -65,10 +65,10 @@ select A.a+10*B.a + 10*C.a, A.a+10*B.a + 10*C.a, 'filler'
from t0 A, t0 B, t0 C; from t0 A, t0 B, t0 C;
explain update t1 set a=a+1 where 3>4; explain update t1 set a=a+1 where 3>4;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
explain update t1 set a=a+1 where a=3 and a=4; explain update t1 set a=a+1 where a=3 and a=4;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible where 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
# This should use an index, possible_keys=NULL because there is no WHERE # This should use an index, possible_keys=NULL because there is no WHERE
explain update t1 set a=a+1 order by a limit 2; explain update t1 set a=a+1 order by a limit 2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
......
...@@ -861,6 +861,14 @@ class PARAM : public RANGE_OPT_PARAM ...@@ -861,6 +861,14 @@ class PARAM : public RANGE_OPT_PARAM
{ {
public: public:
ha_rows quick_rows[MAX_KEY]; ha_rows quick_rows[MAX_KEY];
/*
This will collect 'possible keys' based on the range optimization.
Queries with a JOIN object actually use ref optimizer (see add_key_field)
to collect possible_keys. This is used by single table UPDATE/DELETE.
*/
key_map possible_keys;
longlong baseflag; longlong baseflag;
uint max_key_part, range_count; uint max_key_part, range_count;
...@@ -2956,6 +2964,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2956,6 +2964,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
else if (read_time <= 2.0 && !force_quick_range) else if (read_time <= 2.0 && !force_quick_range)
DBUG_RETURN(0); /* No need for quick select */ DBUG_RETURN(0); /* No need for quick select */
possible_keys.clear_all();
DBUG_PRINT("info",("Time to scan table: %g", read_time)); DBUG_PRINT("info",("Time to scan table: %g", read_time));
keys_to_use.intersect(head->keys_in_use_for_query); keys_to_use.intersect(head->keys_in_use_for_query);
...@@ -2986,6 +2996,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2986,6 +2996,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
param.using_real_indexes= TRUE; param.using_real_indexes= TRUE;
param.remove_jump_scans= TRUE; param.remove_jump_scans= TRUE;
param.force_default_mrr= ordered_output; param.force_default_mrr= ordered_output;
param.possible_keys.clear_all();
thd->no_errors=1; // Don't warn about NULL thd->no_errors=1; // Don't warn about NULL
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0, init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0,
...@@ -3197,6 +3208,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -3197,6 +3208,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
quick= NULL; quick= NULL;
} }
} }
possible_keys= param.possible_keys;
free_mem: free_mem:
free_root(&alloc,MYF(0)); // Return memory & allocator free_root(&alloc,MYF(0)); // Return memory & allocator
...@@ -3204,6 +3216,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -3204,6 +3216,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
thd->no_errors=0; thd->no_errors=0;
} }
DBUG_EXECUTE("info", print_quick(quick, &needed_reg);); DBUG_EXECUTE("info", print_quick(quick, &needed_reg););
/* /*
...@@ -10467,6 +10480,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only, ...@@ -10467,6 +10480,7 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
if (rows != HA_POS_ERROR) if (rows != HA_POS_ERROR)
{ {
param->quick_rows[keynr]= rows; param->quick_rows[keynr]= rows;
param->possible_keys.set_bit(keynr);
if (update_tbl_stats) if (update_tbl_stats)
{ {
param->table->quick_keys.set_bit(keynr); param->table->quick_keys.set_bit(keynr);
......
...@@ -982,6 +982,8 @@ class SQL_SELECT :public Sql_alloc { ...@@ -982,6 +982,8 @@ class SQL_SELECT :public Sql_alloc {
key_map quick_keys; // Possible quick keys key_map quick_keys; // Possible quick keys
key_map needed_reg; // Possible quick keys after prev tables. key_map needed_reg; // Possible quick keys after prev tables.
table_map const_tables,read_tables; table_map const_tables,read_tables;
/* See PARAM::possible_keys */
key_map possible_keys;
bool free_cond; /* Currently not used and always FALSE */ bool free_cond; /* Currently not used and always FALSE */
SQL_SELECT(); SQL_SELECT();
......
...@@ -436,7 +436,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -436,7 +436,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
} }
query_plan.select= select; query_plan.select= select;
query_plan.possible_keys= table->quick_keys; query_plan.possible_keys= select? select->possible_keys: key_map(0);
query_plan.table_rows= table->file->stats.records; query_plan.table_rows= table->file->stats.records;
/* /*
......
...@@ -492,8 +492,8 @@ int mysql_update(THD *thd, ...@@ -492,8 +492,8 @@ int mysql_update(THD *thd,
- if we're running EXPLAIN UPDATE, get out - if we're running EXPLAIN UPDATE, get out
*/ */
query_plan.select= select; query_plan.select= select;
query_plan.possible_keys= table->quick_keys;
query_plan.table_rows= table->file->stats.records; query_plan.table_rows= table->file->stats.records;
query_plan.possible_keys= select? select->possible_keys: key_map(0);
/* /*
Ok, we have generated a query plan for the UPDATE. Ok, we have generated a query plan for the UPDATE.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment