MDEV-33281 Make BNL() hint enable hashed join buffers
Since BNL() hint does not specify which whether hashed or non-hashed join cache should be employed, allow usage of hashed ones where possible
This commit is contained in:
parent
67319f3e8d
commit
af14196b8a
@ -1135,6 +1135,24 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (flat, BNL join)
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (flat, BNL join)
|
||||||
1 SIMPLE t3 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (incremental, BNL join)
|
1 SIMPLE t3 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (incremental, BNL join)
|
||||||
1 SIMPLE t4 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (incremental, BNL join)
|
1 SIMPLE t4 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (incremental, BNL join)
|
||||||
|
set join_cache_level=8;
|
||||||
|
INSERT INTO t2 VALUES (1), (2), (null), (1);
|
||||||
|
# BNLH buffer is used when allowed by JCL setting
|
||||||
|
EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
|
||||||
|
1 SIMPLE t2 hash_ALL NULL #hash#$hj 5 test.t1.a 4 Using where; Using join buffer (flat, BNLH join)
|
||||||
|
# Make sure the hint enables BNL even when JCL=0:
|
||||||
|
set join_cache_level=0;
|
||||||
|
EXPLAIN SELECT /*+BNL(t2) */ * FROM t1, t2 WHERE t1.a=t2.a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
|
||||||
|
1 SIMPLE t2 hash_ALL NULL #hash#$hj 5 test.t1.a 4 Using where; Using join buffer (flat, BNLH join)
|
||||||
|
set join_cache_level=2;
|
||||||
|
EXPLAIN SELECT /*+BNL(t2) */ * FROM t1, t2 WHERE t1.a=t2.a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
|
||||||
|
1 SIMPLE t2 hash_ALL NULL #hash#$hj 5 test.t1.a 4 Using where; Using join buffer (flat, BNLH join)
|
||||||
DROP TABLE t1,t2,t3,t4;
|
DROP TABLE t1,t2,t3,t4;
|
||||||
#
|
#
|
||||||
# Mix of BNL/BKA flat and incremental join buffers for OUTER JOINs
|
# Mix of BNL/BKA flat and incremental join buffers for OUTER JOINs
|
||||||
|
@ -565,6 +565,18 @@ EXPLAIN SELECT /*+ BNL(t2, t3, t4)*/ t1.a
|
|||||||
FROM t1 LEFT JOIN (t2 LEFT JOIN (t3 LEFT JOIN t4 ON 1) ON t2.a) ON 0
|
FROM t1 LEFT JOIN (t2 LEFT JOIN (t3 LEFT JOIN t4 ON 1) ON t2.a) ON 0
|
||||||
WHERE t1.a OR t4.a;
|
WHERE t1.a OR t4.a;
|
||||||
|
|
||||||
|
set join_cache_level=8;
|
||||||
|
INSERT INTO t2 VALUES (1), (2), (null), (1);
|
||||||
|
--echo # BNLH buffer is used when allowed by JCL setting
|
||||||
|
EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a;
|
||||||
|
|
||||||
|
--echo # Make sure the hint enables BNL even when JCL=0:
|
||||||
|
set join_cache_level=0;
|
||||||
|
EXPLAIN SELECT /*+BNL(t2) */ * FROM t1, t2 WHERE t1.a=t2.a;
|
||||||
|
|
||||||
|
set join_cache_level=2;
|
||||||
|
EXPLAIN SELECT /*+BNL(t2) */ * FROM t1, t2 WHERE t1.a=t2.a;
|
||||||
|
|
||||||
DROP TABLE t1,t2,t3,t4;
|
DROP TABLE t1,t2,t3,t4;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1908,7 +1908,7 @@ bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
|
|||||||
OPTIMIZER_SWITCH_MRR);
|
OPTIMIZER_SWITCH_MRR);
|
||||||
const bool force_dsmrr_by_hints=
|
const bool force_dsmrr_by_hints=
|
||||||
hint_key_state(thd, table, keyno, MRR_HINT_ENUM, 0) ||
|
hint_key_state(thd, table, keyno, MRR_HINT_ENUM, 0) ||
|
||||||
hint_table_state(thd, table, BKA_HINT_ENUM, 0);
|
hint_table_state(thd, table, BKA_HINT_ENUM, false);
|
||||||
|
|
||||||
bool doing_cpk_scan= check_cpk_scan(thd, share, keyno, *flags);
|
bool doing_cpk_scan= check_cpk_scan(thd, share, keyno, *flags);
|
||||||
bool using_cpk= primary_file->is_clustering_key(keyno);
|
bool using_cpk= primary_file->is_clustering_key(keyno);
|
||||||
|
@ -483,24 +483,6 @@ bool hint_key_state(const THD *thd, const TABLE *table,
|
|||||||
|
|
||||||
|
|
||||||
bool hint_table_state(const THD *thd, const TABLE *table,
|
bool hint_table_state(const THD *thd, const TABLE *table,
|
||||||
opt_hints_enum type_arg,
|
|
||||||
uint optimizer_switch)
|
|
||||||
{
|
|
||||||
TABLE_LIST *table_list= table->pos_in_table_list;
|
|
||||||
if (table_list->opt_hints_qb)
|
|
||||||
{
|
|
||||||
bool ret_val= false;
|
|
||||||
if (get_hint_state(table_list->opt_hints_table,
|
|
||||||
table_list->opt_hints_qb,
|
|
||||||
type_arg, &ret_val))
|
|
||||||
return ret_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return optimizer_flag(thd, optimizer_switch);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool hint_table_state_or_fallback(const THD *thd, const TABLE *table,
|
|
||||||
opt_hints_enum type_arg,
|
opt_hints_enum type_arg,
|
||||||
bool fallback_value)
|
bool fallback_value)
|
||||||
{
|
{
|
||||||
|
@ -543,21 +543,6 @@ bool hint_key_state(const THD *thd, const TABLE *table,
|
|||||||
uint keyno, opt_hints_enum type_arg,
|
uint keyno, opt_hints_enum type_arg,
|
||||||
uint optimizer_switch);
|
uint optimizer_switch);
|
||||||
|
|
||||||
/**
|
|
||||||
Returns table hint value if hint is specified, returns
|
|
||||||
optimizer switch value if hint is not specified.
|
|
||||||
|
|
||||||
@param thd Pointer to THD object
|
|
||||||
@param tab Pointer to TABLE object
|
|
||||||
@param type_arg Hint type
|
|
||||||
@param optimizer_switch Optimizer switch flag
|
|
||||||
|
|
||||||
@return table hint value if hint is specified,
|
|
||||||
otherwise optimizer switch value.
|
|
||||||
*/
|
|
||||||
bool hint_table_state(const THD *thd, const TABLE *table,
|
|
||||||
opt_hints_enum type_arg,
|
|
||||||
uint optimizer_switch);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns table hint value if hint is specified, returns
|
Returns table hint value if hint is specified, returns
|
||||||
@ -571,7 +556,6 @@ bool hint_table_state(const THD *thd, const TABLE *table,
|
|||||||
@return table hint value if hint is specified,
|
@return table hint value if hint is specified,
|
||||||
otherwise fallback value.
|
otherwise fallback value.
|
||||||
*/
|
*/
|
||||||
bool hint_table_state_or_fallback(const THD *thd, const TABLE *table,
|
bool hint_table_state(const THD *thd, const TABLE *table,
|
||||||
opt_hints_enum type_arg,
|
opt_hints_enum type_arg, bool fallback_value);
|
||||||
bool fallback_value);
|
|
||||||
#endif /* OPT_HINTS_INCLUDED */
|
#endif /* OPT_HINTS_INCLUDED */
|
||||||
|
@ -6662,7 +6662,7 @@ add_key_field(JOIN *join,
|
|||||||
{
|
{
|
||||||
uint optimize= 0;
|
uint optimize= 0;
|
||||||
if (eq_func &&
|
if (eq_func &&
|
||||||
((join->is_allowed_hash_join_access() &&
|
((join->is_allowed_hash_join_access(field->table) &&
|
||||||
field->hash_join_is_possible() &&
|
field->hash_join_is_possible() &&
|
||||||
!(field->table->pos_in_table_list->is_materialized_derived() &&
|
!(field->table->pos_in_table_list->is_materialized_derived() &&
|
||||||
field->table->is_created())) ||
|
field->table->is_created())) ||
|
||||||
@ -9428,8 +9428,7 @@ best_access_path(JOIN *join,
|
|||||||
(2) s is inner table of outer join -> join cache is allowed for outer joins
|
(2) s is inner table of outer join -> join cache is allowed for outer joins
|
||||||
*/
|
*/
|
||||||
if (idx > join->const_tables && best.key == 0 &&
|
if (idx > join->const_tables && best.key == 0 &&
|
||||||
(join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
|
join->is_allowed_hash_join_access(table) &&
|
||||||
join->max_allowed_join_cache_level > 2 &&
|
|
||||||
!bitmap_is_clear_all(eq_join_set) && !disable_jbuf &&
|
!bitmap_is_clear_all(eq_join_set) && !disable_jbuf &&
|
||||||
(!s->emb_sj_nest ||
|
(!s->emb_sj_nest ||
|
||||||
join->allowed_semijoin_with_cache) && // (1)
|
join->allowed_semijoin_with_cache) && // (1)
|
||||||
@ -11468,7 +11467,6 @@ get_costs_for_tables(JOIN *join, table_map remaining_tables, uint idx,
|
|||||||
JOIN_TAB *s;
|
JOIN_TAB *s;
|
||||||
table_map found_tables= 0;
|
table_map found_tables= 0;
|
||||||
bool found_eq_ref= 0;
|
bool found_eq_ref= 0;
|
||||||
bool disable_jbuf= join->thd->variables.join_cache_level == 0;
|
|
||||||
DBUG_ENTER("get_plans_for_tables");
|
DBUG_ENTER("get_plans_for_tables");
|
||||||
|
|
||||||
s= *pos;
|
s= *pos;
|
||||||
@ -11485,6 +11483,11 @@ get_costs_for_tables(JOIN *join, table_map remaining_tables, uint idx,
|
|||||||
sort_end->join_tab= pos;
|
sort_end->join_tab= pos;
|
||||||
sort_end->position= sort_position;
|
sort_end->position= sort_position;
|
||||||
|
|
||||||
|
bool hint_forces_jbuf=
|
||||||
|
hint_table_state(join->thd, s->table, BNL_HINT_ENUM, false);
|
||||||
|
|
||||||
|
bool disable_jbuf=
|
||||||
|
(join->thd->variables.join_cache_level == 0) && !hint_forces_jbuf;
|
||||||
|
|
||||||
Json_writer_object wrapper(thd);
|
Json_writer_object wrapper(thd);
|
||||||
/* Find the best access method from 's' to the current partial plan */
|
/* Find the best access method from 's' to the current partial plan */
|
||||||
@ -14471,11 +14474,17 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
|||||||
add_cond_and_fix(thd, &tmp, tab->select_cond);
|
add_cond_and_fix(thd, &tmp, tab->select_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint max_jcl= join->max_allowed_join_cache_level;
|
||||||
|
bool is_hash_allowed= join->allowed_join_cache_types &
|
||||||
|
JOIN_CACHE_HASHED_BIT;
|
||||||
|
bool is_bnlh_enabled= ((max_jcl == 3 || max_jcl == 4) &&
|
||||||
|
is_hash_allowed) ||
|
||||||
|
hint_table_state(thd, tab->table, BNL_HINT_ENUM, false);
|
||||||
|
bool is_bkah_enabled= (max_jcl > 4 && is_hash_allowed) ||
|
||||||
|
hint_table_state(thd, tab->table, BKA_HINT_ENUM, false);
|
||||||
is_hj= (tab->type == JT_REF || tab->type == JT_EQ_REF) &&
|
is_hj= (tab->type == JT_REF || tab->type == JT_EQ_REF) &&
|
||||||
(join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
|
(is_bnlh_enabled ||
|
||||||
((join->max_allowed_join_cache_level+1)/2 == 2 ||
|
(is_bkah_enabled && is_hash_join_key_no(tab->ref.key))) &&
|
||||||
((join->max_allowed_join_cache_level+1)/2 > 2 &&
|
|
||||||
is_hash_join_key_no(tab->ref.key))) &&
|
|
||||||
(!tab->emb_sj_nest ||
|
(!tab->emb_sj_nest ||
|
||||||
join->allowed_semijoin_with_cache) &&
|
join->allowed_semijoin_with_cache) &&
|
||||||
(!(tab->table->map & join->outer_join) ||
|
(!(tab->table->map & join->outer_join) ||
|
||||||
@ -15631,17 +15640,14 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
|
|||||||
OPTIMIZER_HINTS
|
OPTIMIZER_HINTS
|
||||||
The following hints may influence the choice of join buffering:
|
The following hints may influence the choice of join buffering:
|
||||||
BNL(t1,t2,..): enables BNL and BNLH buffers for the specified tables
|
BNL(t1,t2,..): enables BNL and BNLH buffers for the specified tables
|
||||||
when join_cache_level=0. Effectively it increases
|
when join_cache_level < 4. It effectively increases
|
||||||
join_cache_level to 4 for given tables.
|
join_cache_level to 4 for given tables.
|
||||||
NO_BNL(t1,t2,..): disables BNL/BNLH join buffers, which could have been
|
NO_BNL(t1,t2,..): disables BNL/BNLH join buffers, which could have been
|
||||||
chosen for the specified tables otherwise. Does not
|
chosen for the specified tables otherwise. Does not
|
||||||
prevent employing of BKA/BKAH buffers
|
prevent employing of BKA/BKAH buffers
|
||||||
BKA(t1,t2,..): enables BKA and BKAH buffers for the specified tables
|
BKA(t1,t2,..): enables BKA and BKAH buffers for the specified tables
|
||||||
when optimizer switch join_cache_bka=off. Does not
|
when join_cache_level < 5 and/or
|
||||||
increase join_cache_level, i.e., when join_cache_level=4
|
optimizer switch join_cache_bka=off.
|
||||||
and the hint is specified, BKA join buffers will still
|
|
||||||
not be employed. The hint effectively overrides only
|
|
||||||
optimizer switch join_cache_bka setting.
|
|
||||||
NO_BKA(t1,t2,..): disables BKA/BKAH join buffers, which could have been
|
NO_BKA(t1,t2,..): disables BKA/BKAH join buffers, which could have been
|
||||||
chosen for the specified tables otherwise. However,
|
chosen for the specified tables otherwise. However,
|
||||||
does not prevent employing of BNL/BNLH buffers.
|
does not prevent employing of BNL/BNLH buffers.
|
||||||
@ -15710,21 +15716,18 @@ uint check_join_cache_usage(JOIN_TAB *tab,
|
|||||||
!(join->allowed_join_cache_types & JOIN_CACHE_INCREMENTAL_BIT);
|
!(join->allowed_join_cache_types & JOIN_CACHE_INCREMENTAL_BIT);
|
||||||
bool no_hashed_cache=
|
bool no_hashed_cache=
|
||||||
!(join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT);
|
!(join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT);
|
||||||
bool no_bnl_cache= !hint_table_state_or_fallback(join->thd,
|
bool no_bnl_cache= !hint_table_state(join->thd, tab->tab_list->table,
|
||||||
tab->tab_list->table, BNL_HINT_ENUM, true);
|
BNL_HINT_ENUM, true);
|
||||||
bool no_bka_cache= !hint_table_state_or_fallback(join->thd,
|
bool no_bka_cache= !hint_table_state(join->thd, tab->tab_list->table,
|
||||||
tab->tab_list->table, BKA_HINT_ENUM,
|
BKA_HINT_ENUM, join->allowed_join_cache_types & JOIN_CACHE_BKA_BIT);
|
||||||
join->allowed_join_cache_types & JOIN_CACHE_BKA_BIT);
|
bool hint_forces_bka= hint_table_state(join->thd, tab->tab_list->table,
|
||||||
bool hint_forces_bka= hint_table_state_or_fallback(join->thd,
|
|
||||||
tab->tab_list->table,
|
|
||||||
BKA_HINT_ENUM, false);
|
BKA_HINT_ENUM, false);
|
||||||
join->return_tab= 0;
|
join->return_tab= 0;
|
||||||
|
|
||||||
if (tab->no_forced_join_cache || (no_bnl_cache && no_bka_cache))
|
if (tab->no_forced_join_cache || (no_bnl_cache && no_bka_cache))
|
||||||
goto no_join_cache;
|
goto no_join_cache;
|
||||||
|
|
||||||
if (cache_level < 4 && hint_table_state_or_fallback(join->thd,
|
if (cache_level < 4 && hint_table_state(join->thd, tab->tab_list->table,
|
||||||
tab->tab_list->table,
|
|
||||||
BNL_HINT_ENUM, false))
|
BNL_HINT_ENUM, false))
|
||||||
{
|
{
|
||||||
cache_level= 4; // BNL() hint present, raise join_cache_level to BNLH
|
cache_level= 4; // BNL() hint present, raise join_cache_level to BNLH
|
||||||
@ -32445,6 +32448,13 @@ void JOIN::set_allowed_join_cache_types()
|
|||||||
max_allowed_join_cache_level= thd->variables.join_cache_level;
|
max_allowed_join_cache_level= thd->variables.join_cache_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool JOIN::is_allowed_hash_join_access(const TABLE *table)
|
||||||
|
{
|
||||||
|
return allowed_join_cache_types & JOIN_CACHE_HASHED_BIT &&
|
||||||
|
(max_allowed_join_cache_level > JOIN_CACHE_HASHED_BIT ||
|
||||||
|
hint_table_state(thd, table, BNL_HINT_ENUM, false) ||
|
||||||
|
hint_table_state(thd, table, BKA_HINT_ENUM, false));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Save a query execution plan so that the caller can revert to it if needed,
|
Save a query execution plan so that the caller can revert to it if needed,
|
||||||
|
@ -1885,11 +1885,7 @@ public:
|
|||||||
ulonglong curr_space,
|
ulonglong curr_space,
|
||||||
ulonglong needed_space);
|
ulonglong needed_space);
|
||||||
void set_allowed_join_cache_types();
|
void set_allowed_join_cache_types();
|
||||||
bool is_allowed_hash_join_access()
|
bool is_allowed_hash_join_access(const TABLE *table);
|
||||||
{
|
|
||||||
return MY_TEST(allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
|
|
||||||
max_allowed_join_cache_level > JOIN_CACHE_HASHED_BIT;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
Check if we need to create a temporary table.
|
Check if we need to create a temporary table.
|
||||||
This has to be done if all tables are not already read (const tables)
|
This has to be done if all tables are not already read (const tables)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user