diff options
author | Evgeny Potemkin <epotemkin@mysql.com> | 2010-08-26 13:31:04 +0400 |
---|---|---|
committer | Evgeny Potemkin <epotemkin@mysql.com> | 2010-08-26 13:31:04 +0400 |
commit | b4dc600af919f8a7fa8403535847256161abc1db (patch) | |
tree | a17137c5d0c7416157d45c0ddf6e3fb8190668fc /sql | |
parent | e5a59eee5a0a090cd2cd6f87a63d076f851a7d86 (diff) | |
download | mariadb-git-b4dc600af919f8a7fa8403535847256161abc1db.tar.gz |
Bug #55656: mysqldump can be slower after bug 39653 fix.
After fix for bug 39653 the shortest available secondary index was used for
full table scan. Primary clustered key was used only if no secondary index
can be used. However, when chosen secondary index includes all fields of the
table being scanned it's better to use primary index since the amount of
data to scan is the same but the primary index is clustered.
Now the find_shortest_key function takes this into account.
mysql-test/suite/innodb/r/innodb_mysql.result:
Added a test case for the bug#55656.
mysql-test/suite/innodb/t/innodb_mysql.test:
Added a test case for the bug#55656.
sql/sql_select.cc:
Bug #55656: mysqldump can be slower after bug #39653 fix.
The find_shortest_key function now prefers clustered primary key
if found secondary key includes all fields of the table.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_select.cc | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7ee1762295f..4a32ca34790 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13017,6 +13017,34 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, } +/** + Find shortest key suitable for full table scan. + + @param table Table to scan + @param usable_keys Allowed keys + + @note + As far as + 1) clustered primary key entry data set is a set of all record + fields (key fields and not key fields) and + 2) secondary index entry data is a union of its key fields and + primary key fields (at least InnoDB and its derivatives don't + duplicate primary key fields there, even if the primary and + the secondary keys have a common subset of key fields), + then secondary index entry data is always a subset of primary key entry. + Unfortunately, key_info[nr].key_length doesn't show the length + of key/pointer pair but a sum of key field lengths only, thus + we can't estimate index IO volume comparing only this key_length + value of secondary keys and clustered PK. + So, try secondary keys first, and choose PK only if there are no + usable secondary covering keys or found best secondary key include + all table fields (i.e. same as PK): + + @return + MAX_KEY no suitable key found + key index otherwise +*/ + uint find_shortest_key(TABLE *table, const key_map *usable_keys) { uint best= MAX_KEY; @@ -13029,23 +13057,6 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys) uint min_length= (uint) ~0; for (uint nr=0; nr < table->s->keys ; nr++) { - /* - As far as - 1) clustered primary key entry data set is a set of all record - fields (key fields and not key fields) and - 2) secondary index entry data is a union of its key fields and - primary key fields (at least InnoDB and its derivatives don't - duplicate primary key fields there, even if the primary and - the secondary keys have a common subset of key fields), - then secondary index entry data is always a subset of primary key - entry, and the PK is always longer. - Unfortunately, key_info[nr].key_length doesn't show the length - of key/pointer pair but a sum of key field lengths only, thus - we can't estimate index IO volume comparing only this key_length - value of seconday keys and clustered PK. - So, try secondary keys first, and choose PK only if there are no - usable secondary covering keys: - */ if (nr == usable_clustered_pk) continue; if (usable_keys->is_set(nr)) @@ -13058,7 +13069,20 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys) } } } - return best != MAX_KEY ? best : usable_clustered_pk; + if (usable_clustered_pk != MAX_KEY) + { + /* + If the primary key is clustered and found shorter key covers all table + fields then primary key scan normally would be faster because amount of + data to scan is the same but PK is clustered. + It's safe to compare key parts with table fields since duplicate key + parts aren't allowed. + */ + if (best == MAX_KEY || + table->key_info[best].key_parts >= table->s->fields) + best= usable_clustered_pk; + } + return best; } /** |