Skip to content

Commit d3329e2

Browse files
committed
Merge branch 'mysql-8.0' into mysql-trunk
Change-Id: I0a4748ab944766e822c7e93a3a461dc6a73d1b2b
2 parents 53cfae1 + 5802152 commit d3329e2

File tree

2 files changed

+113
-103
lines changed

2 files changed

+113
-103
lines changed

mysql-test/r/subquery_sj_mat_nosj.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11561,7 +11561,7 @@ WHERE (alias1.col_varchar_key, alias1.col_varchar_nokey) IN
1156111561
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1156211562
1 PRIMARY <derived2> NULL ALL NULL NULL NULL NULL 2 100.00 Using where
1156311563
1 PRIMARY alias2 NULL ALL NULL NULL NULL NULL 11 10.00 Using where; Using join buffer (hash join)
11564-
4 SUBQUERY <derived7> NULL ALL <auto_distinct_key> NULL NULL NULL 2 100.00 NULL
11564+
4 SUBQUERY <derived7> NULL ALL NULL NULL NULL NULL 2 100.00 NULL
1156511565
7 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used
1156611566
8 UNION NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used
1156711567
9 UNION RESULT <union7,8> NULL ALL NULL NULL NULL NULL NULL NULL Using temporary

sql/sql_optimizer.cc

Lines changed: 112 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -9166,153 +9166,163 @@ void JOIN::finalize_derived_keys() {
91669166
assert(query_block->materialized_derived_table_count);
91679167
ASSERT_BEST_REF_IN_JOIN_ORDER(this);
91689168

9169-
bool adjust_key_count = false;
91709169
table_map processed_tables = 0;
91719170

91729171
for (uint i = 0; i < tables; i++) {
9173-
JOIN_TAB *tab = best_ref[i];
9174-
TABLE *table = tab->table();
9175-
Table_ref *table_ref = tab->table_ref;
9172+
TABLE *const table = best_ref[i]->table();
9173+
Table_ref *const tr = best_ref[i]->table_ref;
91769174
/*
9177-
Save chosen key description if:
9178-
1) it's a materialized derived table
9179-
2) it's not yet instantiated
9180-
3) some keys are defined for it
9175+
Process the table's key definitions if:
9176+
1) it is a materialized derived table, and
9177+
2) it is not yet instantiated, and
9178+
3) it has some keys defined, and
9179+
4) it has not yet been processed (may happen if there are more than one
9180+
local references to the same CTE, which are processed on seeing the
9181+
first reference).
91819182
*/
9182-
if (table && table_ref->uses_materialization() && // (1)
9183-
!table->is_created() && // (2)
9184-
table->s->keys > 0) // (3)
9185-
{
9186-
/*
9187-
If there are two local references to the same CTE, and they use
9188-
the same key, the iteration for the second reference is unnecessary.
9189-
*/
9190-
if (processed_tables & table_ref->map()) continue;
9191-
9192-
adjust_key_count = true;
9183+
if (table == nullptr || !tr->uses_materialization() || // (1)
9184+
table->is_created() || // (2)
9185+
table->s->keys == 0 || // (3)
9186+
(processed_tables & tr->map())) { // (4)
9187+
continue;
9188+
}
9189+
/*
9190+
Collect all used keys before starting to shuffle them:
9191+
First create a map from key number to the table using the key:
9192+
*/
9193+
assert(table->s->keys <= MAX_INDEXES);
9194+
TABLE *table_map[MAX_INDEXES];
9195+
for (uint j = 0; j < table->s->keys; j++) {
9196+
table_map[j] = nullptr;
9197+
}
91939198

9194-
Key_map used_keys;
9199+
Key_map used_keys;
91959200

9196-
// Mark all unique indexes as in use, since they have an effect
9197-
// (deduplication) whether any expression refers to them or not.
9198-
// In particular, they are used if we want to materialize a UNION DISTINCT
9199-
// directly into the derived table.
9200-
for (uint key_idx = 0; key_idx < table->s->keys; ++key_idx) {
9201-
if (table->key_info[key_idx].flags & HA_NOSAME) {
9202-
used_keys.set_bit(key_idx);
9203-
}
9201+
// Mark all unique indexes as in use, since they have an effect
9202+
// (deduplication) whether any expression refers to them or not.
9203+
// In particular, they are used if we want to materialize a UNION DISTINCT
9204+
// directly into the derived table.
9205+
for (uint key_idx = 0; key_idx < table->s->keys; ++key_idx) {
9206+
if (table->key_info[key_idx].flags & HA_NOSAME) {
9207+
used_keys.set_bit(key_idx);
92049208
}
9209+
}
9210+
// Same for the hash key used for manual deduplication, if any.
9211+
// (It always has index 0 if it exists.)
9212+
if (table->hash_field) {
9213+
used_keys.set_bit(0);
9214+
}
92059215

9206-
// Same for the hash key used for manual deduplication, if any. (It always
9207-
// has index 0 if it exists.)
9208-
if (table->hash_field) {
9209-
used_keys.set_bit(0);
9210-
}
9216+
Derived_refs_iterator it(tr);
92119217

9212-
Key_use *const keyuse = tab->position()->key;
9213-
if (keyuse == nullptr && used_keys.is_clear_all()) {
9214-
// Nothing uses any keys.
9215-
tab->keys().clear_all();
9216-
tab->const_keys.clear_all();
9218+
while (TABLE *t = it.get_next()) {
9219+
if (t->pos_in_table_list->query_block != query_block) {
92179220
continue;
92189221
}
9222+
JOIN_TAB *jtab = t->reginfo.join_tab;
9223+
Key_use *const keyuse = jtab->position()->key;
9224+
if (keyuse != nullptr) {
9225+
used_keys.set_bit(keyuse->key);
9226+
table_map[keyuse->key] = t;
9227+
} else {
9228+
jtab->keys().clear_all();
9229+
jtab->const_keys.clear_all();
9230+
processed_tables |= t->pos_in_table_list->map();
9231+
}
9232+
}
9233+
/*
9234+
This call is required to establish the initial value for
9235+
TABLE_SHARE::first_unused_tmp_key.
9236+
*/
9237+
(void)table->s->find_first_unused_tmp_key(used_keys);
92199238

9220-
Derived_refs_iterator it(table_ref);
9221-
while (TABLE *t = it.get_next()) {
9222-
/*
9223-
Eliminate possible keys created by this JOIN and which it
9224-
doesn't use.
9225-
Collect all keys of this table which are used by any reference in
9226-
this query block. Any other query block doesn't matter as:
9227-
- either it was optimized before, so it's not using a key we may
9239+
// Process keys in increasing key order
9240+
for (uint j = 0; j < table->s->keys; j++) {
9241+
TABLE *const t = table_map[j];
9242+
if (t == nullptr) continue;
9243+
9244+
/*
9245+
Eliminate possible keys created by this JOIN and which it doesn't use.
9246+
Collect all keys of this table which are used by any reference in
9247+
this query block. Any other query block doesn't matter as:
9248+
- either it was optimized before, so it's not using a key we may
92289249
want to drop.
9229-
- or it was optimized in this same window, so:
9230-
* either we own the window, then any key we may want to
9250+
- or it was optimized in this same window, so:
9251+
* either we own the window, then any key we may want to
92319252
drop is not visible to it.
9232-
* or it owns the window, then we are using only existing
9233-
keys.
9234-
- or it will be optimized after, so it's not using any key yet.
9235-
9236-
used_keys is a mix of possible used keys and existing used keys.
9237-
*/
9238-
if (t->pos_in_table_list->query_block == query_block) {
9239-
JOIN_TAB *jtab = t->reginfo.join_tab;
9240-
Key_use *keyuse_1 = jtab->position()->key;
9241-
if (keyuse_1) used_keys.set_bit(keyuse_1->key);
9242-
}
9243-
}
9253+
* or it owns the window, then we are using only existing keys.
9254+
- or it will be optimized after, so it's not using any key yet.
92449255
9245-
uint new_idx = table->s->find_first_unused_tmp_key(
9246-
used_keys); // Also updates table->s->first_unused_tmp_key.
9247-
if (keyuse == nullptr) {
9256+
used_keys is a mix of possible used keys and existing used keys.
9257+
*/
9258+
if (t->pos_in_table_list->query_block != query_block) {
92489259
continue;
92499260
}
92509261

9262+
JOIN_TAB *jtab = t->reginfo.join_tab;
9263+
Key_use *const keyuse = jtab->position()->key;
9264+
assert(keyuse != nullptr);
9265+
9266+
// Also updates table->s->first_unused_tmp_key.
9267+
uint new_idx = t->s->find_first_unused_tmp_key(used_keys);
9268+
92519269
const uint old_idx = keyuse->key;
92529270
assert(old_idx != new_idx);
92539271

92549272
if (old_idx > new_idx) {
9255-
assert(table->s->owner_of_possible_tmp_keys == query_block);
9256-
it.rewind();
9257-
while (TABLE *t = it.get_next()) {
9273+
assert(t->s->owner_of_possible_tmp_keys == query_block);
9274+
Derived_refs_iterator it1(tr);
9275+
while (TABLE *t1 = it1.get_next()) {
92589276
/*
92599277
Unlike the collection of used_keys, references from other query
92609278
blocks must be considered here, as they need a key_info array
92619279
consistent with the to-be-changed table->s->keys.
92629280
*/
9263-
t->move_tmp_key(old_idx, it.is_first());
9281+
t1->move_tmp_key(old_idx, it1.is_first());
92649282
}
9265-
} else
9283+
used_keys.clear_bit(old_idx);
9284+
used_keys.set_bit(new_idx);
9285+
} else {
92669286
new_idx = old_idx; // Index stays at same slot
9287+
}
92679288

92689289
/*
92699290
If the key was created by earlier-optimized query blocks, and is
92709291
already used by nonlocal references, those don't need any further
9271-
update: they are already setup to use it and we're not moving the
9272-
key.
9292+
update: they are already setup to use it and we're not moving the key.
92739293
If the key was created by this query block, nonlocal references cannot
92749294
possibly be referencing it.
92759295
In both cases, only local references need to update their Key_use.
92769296
*/
9277-
it.rewind();
9278-
while (TABLE *t = it.get_next()) {
9279-
if (t->pos_in_table_list->query_block != query_block) continue;
9280-
JOIN_TAB *jtab = t->reginfo.join_tab;
9281-
Key_use *keyuse_1 = jtab->position()->key;
9282-
if (keyuse_1 && keyuse_1->key == old_idx) {
9283-
processed_tables |= t->pos_in_table_list->map();
9284-
const bool key_is_const = jtab->const_keys.is_set(old_idx);
9297+
Derived_refs_iterator it2(tr);
9298+
while (TABLE *t2 = it2.get_next()) {
9299+
if (t2->pos_in_table_list->query_block != query_block) continue;
9300+
JOIN_TAB *jt2 = t2->reginfo.join_tab;
9301+
Key_use *ku2 = jt2->position()->key;
9302+
if (ku2 != nullptr && ku2->key == old_idx) {
9303+
processed_tables |= t2->pos_in_table_list->map();
9304+
const bool key_is_const = jt2->const_keys.is_set(old_idx);
92859305
// tab->keys() was never set, so must be set
9286-
jtab->keys().clear_all();
9287-
jtab->keys().set_bit(new_idx);
9288-
jtab->const_keys.clear_all();
9289-
if (key_is_const) tab->const_keys.set_bit(new_idx);
9290-
for (Key_use *kit = keyuse_1;
9291-
kit->table_ref == jtab->table_ref && kit->key == old_idx; kit++)
9306+
jt2->keys().clear_all();
9307+
jt2->keys().set_bit(new_idx);
9308+
jt2->const_keys.clear_all();
9309+
if (key_is_const) jt2->const_keys.set_bit(new_idx);
9310+
for (Key_use *kit = ku2;
9311+
kit->table_ref == jt2->table_ref && kit->key == old_idx; kit++) {
92929312
kit->key = new_idx;
9313+
}
92939314
}
92949315
}
92959316
}
9296-
}
92979317

9298-
if (!adjust_key_count) return;
9318+
// Finally, we know how many keys remain in the table.
9319+
if (table->s->owner_of_possible_tmp_keys != query_block) continue;
92999320

9300-
// Finally we know how many keys remain in the table.
9301-
for (uint i = 0; i < tables; i++) {
9302-
JOIN_TAB *tab = best_ref[i];
9303-
TABLE *table = tab->table();
9304-
Table_ref *table_ref = tab->table_ref;
9305-
if (table && table_ref->uses_materialization() && !table->is_created() &&
9306-
table->s->keys > 0) {
9307-
if (table->s->owner_of_possible_tmp_keys != query_block) continue;
9308-
/*
9309-
Release lock. As a bonus, avoid double work when this loop
9310-
later processes another local reference to the same table (similar to
9311-
the processed_tables map in the first loop).
9312-
*/
9313-
table->s->owner_of_possible_tmp_keys = nullptr;
9314-
Derived_refs_iterator it(table_ref);
9315-
while (TABLE *t = it.get_next()) t->drop_unused_tmp_keys(it.is_first());
9321+
// Release lock:
9322+
table->s->owner_of_possible_tmp_keys = nullptr;
9323+
it.rewind();
9324+
while (TABLE *t = it.get_next()) {
9325+
t->drop_unused_tmp_keys(it.is_first());
93169326
}
93179327
}
93189328
}

0 commit comments

Comments
 (0)