diff options
author | Gleb Shchepa <gshchepa@mysql.com> | 2010-06-23 00:32:29 +0400 |
---|---|---|
committer | Gleb Shchepa <gshchepa@mysql.com> | 2010-06-23 00:32:29 +0400 |
commit | da4d23277f94d9b952cc38504f30014945b3f216 (patch) | |
tree | 80a563de65cd97436e44b18e7f1b0dc143bca887 /sql/sql_update.cc | |
parent | a4baec5c13ae533f8521b96d3e3d2df113129df3 (diff) | |
download | mariadb-git-da4d23277f94d9b952cc38504f30014945b3f216.tar.gz |
Bug #30584: delete with order by and limit clauses does not
use limit efficiently
Bug #36569: UPDATE ... WHERE ... ORDER BY... always does a
filesort even if not required
Also two bugs reported after QA review (before the commit
of bugs above to public trees, no documentation needed):
Bug #53737: Performance regressions after applying patch
for bug 36569
Bug #53742: UPDATEs have no effect after applying patch
for bug 36569
Execution of single-table UPDATE and DELETE statements did not use the
same optimizer as was used in the compilation of SELECT statements.
Instead, it had an optimizer of its own that did not take into account
that you can omit sorting by retrieving rows using an index.
Extra optimization has been added: when applicable, single-table
UPDATE/DELETE statements use an existing index instead of filesort. A
corresponding SELECT query would do the former.
Also handling of the DESC ordering expression has been added when
reverse index scan is applicable.
From now on most single table UPDATE and DELETE statements show the
same disk access patterns as the corresponding SELECT query. We verify
this by comparing the result of SHOW STATUS LIKE 'Sort%
Currently the get_index_for_order function
a) checks quick select index (if any) for compatibility with the
ORDER expression list or
b) chooses the cheapest available compatible index, but only if
the index scan is cheaper than filesort.
Second way is implemented by the new test_if_cheaper_ordering
function (extracted part the test_if_skip_sort_order()).
Diffstat (limited to 'sql/sql_update.cc')
-rw-r--r-- | sql/sql_update.cc | 41 |
1 files changed, 17 insertions, 24 deletions
diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 127368cef5c..25c1fd6fa1e 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -203,12 +203,13 @@ int mysql_update(THD *thd, { bool using_limit= limit != HA_POS_ERROR; bool safe_update= test(thd->variables.option_bits & OPTION_SAFE_UPDATES); - bool used_key_is_modified, transactional_table, will_batch; + bool used_key_is_modified= FALSE, transactional_table, will_batch; bool can_compare_record; int res; int error, loc_error; - uint used_index= MAX_KEY, dup_key_found; + uint used_index, dup_key_found; bool need_sort= TRUE; + bool reverse= FALSE; #ifndef NO_EMBEDDED_ACCESS_CHECKS uint want_privilege; #endif @@ -358,11 +359,7 @@ int mysql_update(THD *thd, my_ok(thd); // No matching records DBUG_RETURN(0); } - if (!select && limit != HA_POS_ERROR) - { - if ((used_index= get_index_for_order(table, order, limit)) != MAX_KEY) - need_sort= FALSE; - } + /* If running in safe sql mode, don't allow updates without keys */ if (table->quick_keys.is_clear_all()) { @@ -378,24 +375,20 @@ int mysql_update(THD *thd, table->mark_columns_needed_for_update(); - /* Check if we are modifying a key that we are used to search with */ - - if (select && select->quick) - { - used_index= select->quick->index; - used_key_is_modified= (!select->quick->unique_key_range() && - select->quick->is_keys_used(table->write_set)); + table->update_const_key_parts(conds); + order= simple_remove_const(order, conds); + + used_index= get_index_for_order(order, table, select, limit, + &need_sort, &reverse); + if (need_sort) + { // Assign table scan index to check below for modified key fields: + used_index= table->file->key_used_on_scan; } - else - { - used_key_is_modified= 0; - if (used_index == MAX_KEY) // no index for sort order - used_index= table->file->key_used_on_scan; - if (used_index != MAX_KEY) - used_key_is_modified= is_key_used(table, used_index, table->write_set); + if (used_index != MAX_KEY) + { // Check if we are modifying a key that we are used to search with: + used_key_is_modified= is_key_used(table, used_index, table->write_set); } - #ifdef WITH_PARTITION_STORAGE_ENGINE if (used_key_is_modified || order || partition_key_modified(table, table->write_set)) @@ -414,7 +407,7 @@ int mysql_update(THD *thd, table->use_all_columns(); } - /* note: We avoid sorting avoid if we sort on the used index */ + /* note: We avoid sorting if we sort on the used index */ if (order && (need_sort || used_key_is_modified)) { /* @@ -476,7 +469,7 @@ int mysql_update(THD *thd, if (used_index == MAX_KEY || (select && select->quick)) init_read_record(&info, thd, table, select, 0, 1, FALSE); else - init_read_record_idx(&info, thd, table, 1, used_index); + init_read_record_idx(&info, thd, table, 1, used_index, reverse); thd_proc_info(thd, "Searching rows for update"); ha_rows tmp_limit= limit; |