summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2013-10-09 13:07:46 +0400
committerSergey Petrunya <psergey@askmonty.org>2013-10-09 13:07:46 +0400
commit3c6ac6694d291dc454af6f9042c9217afd7fff9b (patch)
treeab9360d4e28c4ecddfccaf927c3f65a93ce683e9 /sql
parent161d68759433b0315a6b95209d3db86be411a686 (diff)
downloadmariadb-git-3c6ac6694d291dc454af6f9042c9217afd7fff9b.tar.gz
MDEV-3798: EXPLAIN UPDATE/DELETE
- Produce correct #rows for ORDER BY ... LIMIT N queries that take advantage of ordered index read to read only N rows.
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_delete.cc12
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_select.cc7
-rw-r--r--sql/sql_select.h3
-rw-r--r--sql/sql_update.cc12
5 files changed, 28 insertions, 10 deletions
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 15dfe3e6c7c..00193800b93 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 9515079e75f..c5b9c1eada2 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 b99b41915f6..a51fcd07b58 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 71760ea76f5..48515042a02 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 5b2333657e1..a5f81a9e89e 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);