Skip to content

Commit 648b547

Browse files
author
Varun Gupta
committed
MDEV-22399: Remove multiple calls to enable and disable Handler::keyread and perform it after the plan refinement phase is done
Introduce a function to enable keyreads for indexes and use this function when all the decision of plan refinement phase are done.
1 parent 70d4e55 commit 648b547

File tree

2 files changed

+111
-71
lines changed

2 files changed

+111
-71
lines changed

sql/sql_select.cc

Lines changed: 110 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,36 +1755,6 @@ JOIN::init_range_rowid_filters()
17551755
}
17561756

17571757

1758-
int JOIN::init_join_caches()
1759-
{
1760-
JOIN_TAB *tab;
1761-
1762-
for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
1763-
tab;
1764-
tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
1765-
{
1766-
TABLE *table= tab->table;
1767-
if (table->file->keyread_enabled())
1768-
{
1769-
if (!(table->file->index_flags(table->file->keyread, 0, 1) & HA_CLUSTERED_INDEX))
1770-
table->mark_columns_used_by_index(table->file->keyread, table->read_set);
1771-
}
1772-
else if ((tab->read_first_record == join_read_first ||
1773-
tab->read_first_record == join_read_last) &&
1774-
!tab->filesort && table->covering_keys.is_set(tab->index) &&
1775-
!table->no_keyread)
1776-
{
1777-
table->prepare_for_keyread(tab->index, table->read_set);
1778-
}
1779-
if (tab->cache && tab->cache->init(select_options & SELECT_DESCRIBE))
1780-
revise_cache_usage(tab);
1781-
else
1782-
tab->remove_redundant_bnl_scan_conds();
1783-
}
1784-
return 0;
1785-
}
1786-
1787-
17881758
/**
17891759
global select optimisation.
17901760

@@ -3007,8 +2977,7 @@ int JOIN::optimize_stage2()
30072977
if (make_aggr_tables_info())
30082978
DBUG_RETURN(1);
30092979

3010-
if (init_join_caches())
3011-
DBUG_RETURN(1);
2980+
init_join_cache_and_keyread();
30122981

30132982
if (init_range_rowid_filters())
30142983
DBUG_RETURN(1);
@@ -13137,17 +13106,15 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
1313713106
/* Only happens with outer joins */
1313813107
tab->read_first_record= tab->type == JT_SYSTEM ? join_read_system
1313913108
: join_read_const;
13140-
if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread)
13141-
table->file->ha_start_keyread(tab->ref.key);
13142-
else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered())
13109+
if (!(table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) &&
13110+
(!jcl || jcl > 4) && !tab->ref.is_access_triggered())
1314313111
push_index_cond(tab, tab->ref.key);
1314413112
break;
1314513113
case JT_EQ_REF:
1314613114
tab->read_record.unlock_row= join_read_key_unlock_row;
1314713115
/* fall through */
13148-
if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread)
13149-
table->file->ha_start_keyread(tab->ref.key);
13150-
else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered())
13116+
if (!(table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) &&
13117+
(!jcl || jcl > 4) && !tab->ref.is_access_triggered())
1315113118
push_index_cond(tab, tab->ref.key);
1315213119
break;
1315313120
case JT_REF_OR_NULL:
@@ -13159,9 +13126,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
1315913126
}
1316013127
delete tab->quick;
1316113128
tab->quick=0;
13162-
if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread)
13163-
table->file->ha_start_keyread(tab->ref.key);
13164-
else if ((!jcl || jcl > 4) && !tab->ref.is_access_triggered())
13129+
if (!(table->covering_keys.is_set(tab->ref.key) && !table->no_keyread) &&
13130+
(!jcl || jcl > 4) && !tab->ref.is_access_triggered())
1316513131
push_index_cond(tab, tab->ref.key);
1316613132
break;
1316713133
case JT_ALL:
@@ -13220,12 +13186,11 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
1322013186
}
1322113187
if (!table->no_keyread)
1322213188
{
13223-
if (tab->select && tab->select->quick &&
13224-
tab->select->quick->index != MAX_KEY && //not index_merge
13225-
table->covering_keys.is_set(tab->select->quick->index))
13226-
table->file->ha_start_keyread(tab->select->quick->index);
13227-
else if (!table->covering_keys.is_clear_all() &&
13228-
!(tab->select && tab->select->quick))
13189+
if (!(tab->select && tab->select->quick &&
13190+
tab->select->quick->index != MAX_KEY && //not index_merge
13191+
table->covering_keys.is_set(tab->select->quick->index)) &&
13192+
(!table->covering_keys.is_clear_all() &&
13193+
!(tab->select && tab->select->quick)))
1322913194
{ // Only read index tree
1323013195
if (tab->loosescan_match_tab)
1323113196
tab->index= tab->loosescan_key;
@@ -13252,7 +13217,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
1325213217
}
1325313218
if (tab->select && tab->select->quick &&
1325413219
tab->select->quick->index != MAX_KEY &&
13255-
!tab->table->file->keyread_enabled())
13220+
!tab->table->covering_keys.is_set(tab->select->quick->index))
1325613221
push_index_cond(tab, tab->select->quick->index);
1325713222
}
1325813223
break;
@@ -23604,15 +23569,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
2360423569
bool quick_created=
2360523570
(select && select->quick && select->quick!=save_quick);
2360623571

23607-
/*
23608-
If ref_key used index tree reading only ('Using index' in EXPLAIN),
23609-
and best_key doesn't, then revert the decision.
23610-
*/
23611-
if (table->covering_keys.is_set(best_key) && !table->no_keyread)
23612-
table->file->ha_start_keyread(best_key);
23613-
else
23614-
table->file->ha_end_keyread();
23615-
2361623572
if (!quick_created)
2361723573
{
2361823574
if (select) // Throw any existing quick select
@@ -23653,7 +23609,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
2365323609
tab->ref.key_parts= 0;
2365423610
if (select_limit < table->stat_records())
2365523611
tab->limit= select_limit;
23656-
table->file->ha_end_keyread();
2365723612
}
2365823613
}
2365923614
else if (tab->type != JT_ALL || tab->select->quick)
@@ -23754,14 +23709,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
2375423709
{
2375523710
delete save_quick;
2375623711
save_quick= NULL;
23757-
23758-
/*
23759-
'delete save_quick' disabled key reads. Enable key read if the new
23760-
index is an covering key
23761-
*/
23762-
if (select->quick && !select->head->no_keyread &&
23763-
select->head->covering_keys.is_set(select->quick->index))
23764-
select->head->file->ha_start_keyread(select->quick->index);
2376523712
}
2376623713
if (orig_cond_saved && !changed_key)
2376723714
tab->set_cond(orig_cond);
@@ -23776,9 +23723,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
2377623723
{
2377723724
delete select->quick;
2377823725
select->quick= save_quick;
23779-
if (select->quick && !select->head->no_keyread &&
23780-
select->head->covering_keys.is_set(select->quick->index))
23781-
select->head->file->ha_start_keyread(select->quick->index);
2378223726
}
2378323727
if (orig_cond_saved)
2378423728
tab->set_cond(orig_cond);
@@ -28593,7 +28537,6 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
2859328537
*new_select_limit= has_limit ? best_select_limit : table_records;
2859428538
if (new_used_key_parts != NULL)
2859528539
*new_used_key_parts= best_key_parts;
28596-
table->file->ha_end_keyread();
2859728540
DBUG_RETURN(TRUE);
2859828541
}
2859928542

@@ -29327,6 +29270,103 @@ void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join,
2932729270
}
2932829271

2932929272

29273+
/*
29274+
@brief
29275+
Initialize join cache and enable keyread
29276+
*/
29277+
void JOIN::init_join_cache_and_keyread()
29278+
{
29279+
JOIN_TAB *tab;
29280+
for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITHOUT_CONST_TABLES);
29281+
tab;
29282+
tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS))
29283+
{
29284+
TABLE *table= tab->table;
29285+
switch (tab->type) {
29286+
case JT_SYSTEM:
29287+
case JT_CONST:
29288+
case JT_FT:
29289+
case JT_UNKNOWN:
29290+
case JT_MAYBE_REF:
29291+
break;
29292+
case JT_EQ_REF:
29293+
case JT_REF_OR_NULL:
29294+
case JT_REF:
29295+
if (table->covering_keys.is_set(tab->ref.key) && !table->no_keyread)
29296+
table->file->ha_start_keyread(tab->ref.key);
29297+
break;
29298+
case JT_HASH:
29299+
case JT_ALL:
29300+
SQL_SELECT *select;
29301+
select= tab->select ? tab->select :
29302+
(tab->filesort ? tab->filesort->select : NULL);
29303+
if (select && select->quick && select->quick->index != MAX_KEY &&
29304+
table->covering_keys.is_set(select->quick->index) &&
29305+
!table->no_keyread)
29306+
table->file->ha_start_keyread(select->quick->index);
29307+
break;
29308+
case JT_HASH_NEXT:
29309+
case JT_NEXT:
29310+
if ((tab->read_first_record == join_read_first ||
29311+
tab->read_first_record == join_read_last) &&
29312+
table->covering_keys.is_set(tab->index) &&
29313+
!table->no_keyread)
29314+
{
29315+
DBUG_ASSERT(!tab->filesort);
29316+
table->file->ha_start_keyread(tab->index);
29317+
}
29318+
break;
29319+
default:
29320+
break;
29321+
/* purecov: end */
29322+
}
29323+
29324+
if (table->file->keyread_enabled())
29325+
{
29326+
/*
29327+
Here we set the read_set bitmap for all covering keys
29328+
except CLUSTERED indexes, with all the key-parts inside the key.
29329+
This is needed specifically for an index that contains virtual column.
29330+
29331+
Example:
29332+
Lets say we have this query
29333+
SELECT b FROM t1;
29334+
29335+
and the table definition is like
29336+
CREATE TABLE t1(
29337+
a varchar(10) DEFAULT NULL,
29338+
b varchar(255) GENERATED ALWAYS AS (a) VIRTUAL,
29339+
KEY key1 (b));
29340+
29341+
So we a virtual column b and an index key1 defined on the virtual
29342+
column. So if a query uses a vcol, base columns that it
29343+
depends on are automatically added to the read_set - because they're
29344+
needed to calculate the vcol.
29345+
But if we're doing keyread, vcol is taken
29346+
from the index, not calculated, and base columns do not need to be
29347+
in the read set. To ensure this we try to set the read_set to only
29348+
the key-parts of the indexes.
29349+
29350+
Another side effect of this is
29351+
Lets say you have a query
29352+
select a, b from t1
29353+
and there is an index key1 (a,b,c)
29354+
then as key1 is covering and we would have the keyread enable for
29355+
this key, so the below call will also set the read_set for column
29356+
c, which is not a problem as we read all the columns from the index
29357+
tuple.
29358+
*/
29359+
if (!(table->file->index_flags(table->file->keyread, 0, 1) & HA_CLUSTERED_INDEX))
29360+
table->mark_columns_used_by_index(table->file->keyread, table->read_set);
29361+
}
29362+
if (tab->cache && tab->cache->init(select_options & SELECT_DESCRIBE))
29363+
revise_cache_usage(tab);
29364+
else
29365+
tab->remove_redundant_bnl_scan_conds();
29366+
}
29367+
}
29368+
29369+
2933029370
/**
2933129371
@} (end of group Query_Optimizer)
2933229372
*/

sql/sql_select.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1642,7 +1642,6 @@ class JOIN :public Sql_alloc
16421642
bool flatten_subqueries();
16431643
bool optimize_unflattened_subqueries();
16441644
bool optimize_constant_subqueries();
1645-
int init_join_caches();
16461645
bool make_range_rowid_filters();
16471646
bool init_range_rowid_filters();
16481647
bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
@@ -1826,6 +1825,7 @@ class JOIN :public Sql_alloc
18261825
bool add_having_as_table_cond(JOIN_TAB *tab);
18271826
bool make_aggr_tables_info();
18281827
bool add_fields_for_current_rowid(JOIN_TAB *cur, List<Item> *fields);
1828+
void init_join_cache_and_keyread();
18291829
};
18301830

18311831
enum enum_with_bush_roots { WITH_BUSH_ROOTS, WITHOUT_BUSH_ROOTS};

0 commit comments

Comments
 (0)