diff --git a/mysql-test/r/explain_non_select.result b/mysql-test/r/explain_non_select.result index d118cd7b4e70dff2f22b0859521a8c30ce7e2aeb..7d5228de0ee322baebf9ac26955f411683ef0b12 100644 --- a/mysql-test/r/explain_non_select.result +++ b/mysql-test/r/explain_non_select.result @@ -21,7 +21,7 @@ from t0 A, t0 B, t0 C; # This should use an index, possible_keys=NULL because there is no WHERE explain delete from t1 order by a limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL a NULL NULL 512 +1 SIMPLE t1 index NULL a NULL NULL 2 # This should use range, possible_keys={a,b} explain delete from t1 where a<20 and b < 10; id select_type table type possible_keys key key_len ref rows Extra @@ -72,7 +72,7 @@ id select_type table type possible_keys key key_len ref rows Extra # 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; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 512 +1 SIMPLE t1 ALL NULL NULL NULL NULL 512 Using filesort # This should use range, possible_keys={a,b} explain update t1 set filler='fooo' where a<20 and b < 10; id select_type table type possible_keys key key_len ref rows Extra @@ -80,11 +80,11 @@ id select_type table type possible_keys key key_len ref rows Extra # This should use ALL + filesort explain update t1 set filler='fooo' order by a+1 limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 512 +1 SIMPLE t1 ALL NULL NULL NULL NULL 512 Using filesort # This should use range + using filesort explain update t1 set filler='fooo' where a<20 order by b limit 2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range a a 5 NULL 1 Using where +1 SIMPLE t1 range a a 5 NULL 1 Using where; Using filesort # Try some subqueries: explain update t1 set filler='fooo' where a < (select max(a) from t0); id select_type table type possible_keys key key_len ref rows Extra diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 15dfe3e6c7c58c5f215de4c6ef7238946557c258..00193800b93db2ff68ca450d4c08552d1ae608bf 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -59,7 +59,7 @@ void Delete_plan::save_explain_data(Explain_query *query) { explain->deleting_all_rows= true; explain->select_type= "SIMPLE"; - explain->rows= table_rows; + explain->rows= scanned_rows; } else { @@ -161,7 +161,7 @@ void Update_plan::save_explain_data_intern(Explain_query *query, } // key_len stays NULL } - explain->rows= select ? select->records : table_rows; + explain->rows= scanned_rows; if (select && select->quick && select->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE) @@ -421,6 +421,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (options & OPTION_QUICK) (void) table->file->extra(HA_EXTRA_QUICK); + query_plan.scanned_rows= select? select->records: table->file->stats.records; if (order) { table->update_const_key_parts(conds); @@ -432,14 +433,19 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, query_plan.index= MAX_KEY; } else + { + ha_rows scanned_limit= query_plan.scanned_rows; query_plan.index= get_index_for_order(order, table, select, limit, + &scanned_limit, &query_plan.using_filesort, &reverse); + if (!query_plan.using_filesort) + query_plan.scanned_rows= scanned_limit; + } } query_plan.select= select; query_plan.possible_keys= select? select->possible_keys: key_map(0); - query_plan.table_rows= table->file->stats.records; /* Ok, we have generated a query plan for the DELETE. diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 9515079e75fa08a3c425a105ad70152a0acb6827..c5b9c1eada20a4c9eb526c92b8a4035b738ca041 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2397,7 +2397,7 @@ public: TABLE *table; SQL_SELECT *select; uint index; - ha_rows table_rows; /* Use if select==NULL */ + ha_rows scanned_rows; /* Top-level select_lex. Most of its fields are not used, we need it only to get to the subqueries. @@ -2440,7 +2440,7 @@ public: void set_delete_all_rows(ha_rows rows_arg) { deleting_all_rows= true; - table_rows= rows_arg; + scanned_rows= rows_arg; } void save_explain_data(Explain_query *query); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b99b41915f6421e6b2506cdc5036e540cb5a00a5..a51fcd07b58b61cf0833716f712763a5e1f75ed4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24126,6 +24126,8 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, @param table Table to find a key @param select Pointer to access/update select->quick (if any) @param limit LIMIT clause parameter + @param [out] scanned_limit How many records we expect to scan + Valid if *need_sort=FALSE. @param [out] need_sort TRUE if filesort needed @param [out] reverse TRUE if the key is reversed again given ORDER (undefined if key == MAX_KEY) @@ -24143,7 +24145,8 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, */ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, - ha_rows limit, bool *need_sort, bool *reverse) + ha_rows limit, ha_rows *scanned_limit, + bool *need_sort, bool *reverse) { if (!order) { @@ -24185,6 +24188,7 @@ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, { select->set_quick(reverse_quick); *need_sort= FALSE; + *scanned_limit= select->quick->records; return select->quick->index; } else @@ -24213,6 +24217,7 @@ uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, !is_key_used(table, key, table->write_set)) { *need_sort= FALSE; + *scanned_limit= limit; *reverse= (direction < 0); return key; } diff --git a/sql/sql_select.h b/sql/sql_select.h index 71760ea76f5992718f5299460b3fb1cfb7cc2f74..48515042a02c888d30e4a9b95324a2307f6bfbab 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1833,7 +1833,8 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly, SELECT_LEX *select_lex, uint8 select_options); uint get_index_for_order(ORDER *order, TABLE *table, SQL_SELECT *select, - ha_rows limit, bool *need_sort, bool *reverse); + ha_rows limit, ha_rows *scanned_limit, + bool *need_sort, bool *reverse); ORDER *simple_remove_const(ORDER *order, COND *where); bool const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field= NULL, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 5b2333657e1a137d642868a82c7d720508afb500..a5f81a9e89ec1f15a45db9871c9883ee08593320 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -456,6 +456,7 @@ int mysql_update(THD *thd, table->update_const_key_parts(conds); order= simple_remove_const(order, conds); + query_plan.scanned_rows= select? select->records: table->file->stats.records; if (select && select->quick && select->quick->unique_key_range()) { // Single row select (always "ordered"): Ok to use with key field UPDATE @@ -465,8 +466,12 @@ int mysql_update(THD *thd, } else { + ha_rows scanned_limit= query_plan.scanned_rows; query_plan.index= get_index_for_order(order, table, select, limit, - &need_sort, &reverse); + &scanned_limit, &need_sort, &reverse); + if (!need_sort) + query_plan.scanned_rows= scanned_limit; + if (select && select->quick) { DBUG_ASSERT(need_sort || query_plan.index == select->quick->index); @@ -492,7 +497,6 @@ int mysql_update(THD *thd, - if we're running EXPLAIN UPDATE, get out */ query_plan.select= select; - query_plan.table_rows= table->file->stats.records; query_plan.possible_keys= select? select->possible_keys: key_map(0); if (used_key_is_modified || order || @@ -504,7 +508,6 @@ int mysql_update(THD *thd, query_plan.using_io_buffer= true; } - query_plan.save_explain_data(thd->lex->explain); /* Ok, we have generated a query plan for the UPDATE. @@ -513,6 +516,8 @@ int mysql_update(THD *thd, */ if (thd->lex->describe) goto exit_without_my_ok; + query_plan.save_explain_data(thd->lex->explain); + thd->apc_target.enable(); apc_target_enabled= true; DBUG_EXECUTE_IF("show_explain_probe_update_exec_start", @@ -1041,6 +1046,7 @@ err: exit_without_my_ok: DBUG_ASSERT(!apc_target_enabled); + query_plan.save_explain_data(thd->lex->explain); int err2= thd->lex->explain->send_explain(thd);