Skip to content

Commit af14196

Browse files
committed
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
1 parent 67319f3 commit af14196

File tree

7 files changed

+69
-67
lines changed

7 files changed

+69
-67
lines changed

mysql-test/main/opt_hints.result

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,24 @@ id select_type table type possible_keys key key_len ref rows Extra
11351135
1 SIMPLE t2 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (flat, BNL join)
11361136
1 SIMPLE t3 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (incremental, BNL join)
11371137
1 SIMPLE t4 ALL NULL NULL NULL NULL 0 Using where; Using join buffer (incremental, BNL join)
1138+
set join_cache_level=8;
1139+
INSERT INTO t2 VALUES (1), (2), (null), (1);
1140+
# BNLH buffer is used when allowed by JCL setting
1141+
EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a;
1142+
id select_type table type possible_keys key key_len ref rows Extra
1143+
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
1144+
1 SIMPLE t2 hash_ALL NULL #hash#$hj 5 test.t1.a 4 Using where; Using join buffer (flat, BNLH join)
1145+
# Make sure the hint enables BNL even when JCL=0:
1146+
set join_cache_level=0;
1147+
EXPLAIN SELECT /*+BNL(t2) */ * FROM t1, t2 WHERE t1.a=t2.a;
1148+
id select_type table type possible_keys key key_len ref rows Extra
1149+
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
1150+
1 SIMPLE t2 hash_ALL NULL #hash#$hj 5 test.t1.a 4 Using where; Using join buffer (flat, BNLH join)
1151+
set join_cache_level=2;
1152+
EXPLAIN SELECT /*+BNL(t2) */ * FROM t1, t2 WHERE t1.a=t2.a;
1153+
id select_type table type possible_keys key key_len ref rows Extra
1154+
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where
1155+
1 SIMPLE t2 hash_ALL NULL #hash#$hj 5 test.t1.a 4 Using where; Using join buffer (flat, BNLH join)
11381156
DROP TABLE t1,t2,t3,t4;
11391157
#
11401158
# Mix of BNL/BKA flat and incremental join buffers for OUTER JOINs

mysql-test/main/opt_hints.test

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,18 @@ EXPLAIN SELECT /*+ BNL(t2, t3, t4)*/ t1.a
565565
FROM t1 LEFT JOIN (t2 LEFT JOIN (t3 LEFT JOIN t4 ON 1) ON t2.a) ON 0
566566
WHERE t1.a OR t4.a;
567567

568+
set join_cache_level=8;
569+
INSERT INTO t2 VALUES (1), (2), (null), (1);
570+
--echo # BNLH buffer is used when allowed by JCL setting
571+
EXPLAIN SELECT * FROM t1, t2 WHERE t1.a=t2.a;
572+
573+
--echo # Make sure the hint enables BNL even when JCL=0:
574+
set join_cache_level=0;
575+
EXPLAIN SELECT /*+BNL(t2) */ * FROM t1, t2 WHERE t1.a=t2.a;
576+
577+
set join_cache_level=2;
578+
EXPLAIN SELECT /*+BNL(t2) */ * FROM t1, t2 WHERE t1.a=t2.a;
579+
568580
DROP TABLE t1,t2,t3,t4;
569581

570582

sql/multi_range_read.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,7 @@ bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
19081908
OPTIMIZER_SWITCH_MRR);
19091909
const bool force_dsmrr_by_hints=
19101910
hint_key_state(thd, table, keyno, MRR_HINT_ENUM, 0) ||
1911-
hint_table_state(thd, table, BKA_HINT_ENUM, 0);
1911+
hint_table_state(thd, table, BKA_HINT_ENUM, false);
19121912

19131913
bool doing_cpk_scan= check_cpk_scan(thd, share, keyno, *flags);
19141914
bool using_cpk= primary_file->is_clustering_key(keyno);

sql/opt_hints.cc

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -483,24 +483,6 @@ bool hint_key_state(const THD *thd, const TABLE *table,
483483

484484

485485
bool hint_table_state(const THD *thd, const TABLE *table,
486-
opt_hints_enum type_arg,
487-
uint optimizer_switch)
488-
{
489-
TABLE_LIST *table_list= table->pos_in_table_list;
490-
if (table_list->opt_hints_qb)
491-
{
492-
bool ret_val= false;
493-
if (get_hint_state(table_list->opt_hints_table,
494-
table_list->opt_hints_qb,
495-
type_arg, &ret_val))
496-
return ret_val;
497-
}
498-
499-
return optimizer_flag(thd, optimizer_switch);
500-
}
501-
502-
503-
bool hint_table_state_or_fallback(const THD *thd, const TABLE *table,
504486
opt_hints_enum type_arg,
505487
bool fallback_value)
506488
{

sql/opt_hints.h

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -543,21 +543,6 @@ bool hint_key_state(const THD *thd, const TABLE *table,
543543
uint keyno, opt_hints_enum type_arg,
544544
uint optimizer_switch);
545545

546-
/**
547-
Returns table hint value if hint is specified, returns
548-
optimizer switch value if hint is not specified.
549-
550-
@param thd Pointer to THD object
551-
@param tab Pointer to TABLE object
552-
@param type_arg Hint type
553-
@param optimizer_switch Optimizer switch flag
554-
555-
@return table hint value if hint is specified,
556-
otherwise optimizer switch value.
557-
*/
558-
bool hint_table_state(const THD *thd, const TABLE *table,
559-
opt_hints_enum type_arg,
560-
uint optimizer_switch);
561546

562547
/**
563548
Returns table hint value if hint is specified, returns
@@ -571,7 +556,6 @@ bool hint_table_state(const THD *thd, const TABLE *table,
571556
@return table hint value if hint is specified,
572557
otherwise fallback value.
573558
*/
574-
bool hint_table_state_or_fallback(const THD *thd, const TABLE *table,
575-
opt_hints_enum type_arg,
576-
bool fallback_value);
559+
bool hint_table_state(const THD *thd, const TABLE *table,
560+
opt_hints_enum type_arg, bool fallback_value);
577561
#endif /* OPT_HINTS_INCLUDED */

sql/sql_select.cc

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6662,7 +6662,7 @@ add_key_field(JOIN *join,
66626662
{
66636663
uint optimize= 0;
66646664
if (eq_func &&
6665-
((join->is_allowed_hash_join_access() &&
6665+
((join->is_allowed_hash_join_access(field->table) &&
66666666
field->hash_join_is_possible() &&
66676667
!(field->table->pos_in_table_list->is_materialized_derived() &&
66686668
field->table->is_created())) ||
@@ -9428,8 +9428,7 @@ best_access_path(JOIN *join,
94289428
(2) s is inner table of outer join -> join cache is allowed for outer joins
94299429
*/
94309430
if (idx > join->const_tables && best.key == 0 &&
9431-
(join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
9432-
join->max_allowed_join_cache_level > 2 &&
9431+
join->is_allowed_hash_join_access(table) &&
94339432
!bitmap_is_clear_all(eq_join_set) && !disable_jbuf &&
94349433
(!s->emb_sj_nest ||
94359434
join->allowed_semijoin_with_cache) && // (1)
@@ -11468,7 +11467,6 @@ get_costs_for_tables(JOIN *join, table_map remaining_tables, uint idx,
1146811467
JOIN_TAB *s;
1146911468
table_map found_tables= 0;
1147011469
bool found_eq_ref= 0;
11471-
bool disable_jbuf= join->thd->variables.join_cache_level == 0;
1147211470
DBUG_ENTER("get_plans_for_tables");
1147311471

1147411472
s= *pos;
@@ -11485,6 +11483,11 @@ get_costs_for_tables(JOIN *join, table_map remaining_tables, uint idx,
1148511483
sort_end->join_tab= pos;
1148611484
sort_end->position= sort_position;
1148711485

11486+
bool hint_forces_jbuf=
11487+
hint_table_state(join->thd, s->table, BNL_HINT_ENUM, false);
11488+
11489+
bool disable_jbuf=
11490+
(join->thd->variables.join_cache_level == 0) && !hint_forces_jbuf;
1148811491

1148911492
Json_writer_object wrapper(thd);
1149011493
/* 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)
1447114474
add_cond_and_fix(thd, &tmp, tab->select_cond);
1447214475
}
1447314476

14477+
uint max_jcl= join->max_allowed_join_cache_level;
14478+
bool is_hash_allowed= join->allowed_join_cache_types &
14479+
JOIN_CACHE_HASHED_BIT;
14480+
bool is_bnlh_enabled= ((max_jcl == 3 || max_jcl == 4) &&
14481+
is_hash_allowed) ||
14482+
hint_table_state(thd, tab->table, BNL_HINT_ENUM, false);
14483+
bool is_bkah_enabled= (max_jcl > 4 && is_hash_allowed) ||
14484+
hint_table_state(thd, tab->table, BKA_HINT_ENUM, false);
1447414485
is_hj= (tab->type == JT_REF || tab->type == JT_EQ_REF) &&
14475-
(join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
14476-
((join->max_allowed_join_cache_level+1)/2 == 2 ||
14477-
((join->max_allowed_join_cache_level+1)/2 > 2 &&
14478-
is_hash_join_key_no(tab->ref.key))) &&
14486+
(is_bnlh_enabled ||
14487+
(is_bkah_enabled && is_hash_join_key_no(tab->ref.key))) &&
1447914488
(!tab->emb_sj_nest ||
1448014489
join->allowed_semijoin_with_cache) &&
1448114490
(!(tab->table->map & join->outer_join) ||
@@ -15631,17 +15640,14 @@ end_sj_materialize(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
1563115640
OPTIMIZER_HINTS
1563215641
The following hints may influence the choice of join buffering:
1563315642
BNL(t1,t2,..): enables BNL and BNLH buffers for the specified tables
15634-
when join_cache_level=0. Effectively it increases
15643+
when join_cache_level < 4. It effectively increases
1563515644
join_cache_level to 4 for given tables.
1563615645
NO_BNL(t1,t2,..): disables BNL/BNLH join buffers, which could have been
1563715646
chosen for the specified tables otherwise. Does not
1563815647
prevent employing of BKA/BKAH buffers
1563915648
BKA(t1,t2,..): enables BKA and BKAH buffers for the specified tables
15640-
when optimizer switch join_cache_bka=off. Does not
15641-
increase join_cache_level, i.e., when join_cache_level=4
15642-
and the hint is specified, BKA join buffers will still
15643-
not be employed. The hint effectively overrides only
15644-
optimizer switch join_cache_bka setting.
15649+
when join_cache_level < 5 and/or
15650+
optimizer switch join_cache_bka=off.
1564515651
NO_BKA(t1,t2,..): disables BKA/BKAH join buffers, which could have been
1564615652
chosen for the specified tables otherwise. However,
1564715653
does not prevent employing of BNL/BNLH buffers.
@@ -15710,22 +15716,19 @@ uint check_join_cache_usage(JOIN_TAB *tab,
1571015716
!(join->allowed_join_cache_types & JOIN_CACHE_INCREMENTAL_BIT);
1571115717
bool no_hashed_cache=
1571215718
!(join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT);
15713-
bool no_bnl_cache= !hint_table_state_or_fallback(join->thd,
15714-
tab->tab_list->table, BNL_HINT_ENUM, true);
15715-
bool no_bka_cache= !hint_table_state_or_fallback(join->thd,
15716-
tab->tab_list->table, BKA_HINT_ENUM,
15717-
join->allowed_join_cache_types & JOIN_CACHE_BKA_BIT);
15718-
bool hint_forces_bka= hint_table_state_or_fallback(join->thd,
15719-
tab->tab_list->table,
15720-
BKA_HINT_ENUM, false);
15719+
bool no_bnl_cache= !hint_table_state(join->thd, tab->tab_list->table,
15720+
BNL_HINT_ENUM, true);
15721+
bool no_bka_cache= !hint_table_state(join->thd, tab->tab_list->table,
15722+
BKA_HINT_ENUM, join->allowed_join_cache_types & JOIN_CACHE_BKA_BIT);
15723+
bool hint_forces_bka= hint_table_state(join->thd, tab->tab_list->table,
15724+
BKA_HINT_ENUM, false);
1572115725
join->return_tab= 0;
1572215726

1572315727
if (tab->no_forced_join_cache || (no_bnl_cache && no_bka_cache))
1572415728
goto no_join_cache;
1572515729

15726-
if (cache_level < 4 && hint_table_state_or_fallback(join->thd,
15727-
tab->tab_list->table,
15728-
BNL_HINT_ENUM, false))
15730+
if (cache_level < 4 && hint_table_state(join->thd, tab->tab_list->table,
15731+
BNL_HINT_ENUM, false))
1572915732
{
1573015733
cache_level= 4; // BNL() hint present, raise join_cache_level to BNLH
1573115734
}
@@ -32445,6 +32448,13 @@ void JOIN::set_allowed_join_cache_types()
3244532448
max_allowed_join_cache_level= thd->variables.join_cache_level;
3244632449
}
3244732450

32451+
bool JOIN::is_allowed_hash_join_access(const TABLE *table)
32452+
{
32453+
return allowed_join_cache_types & JOIN_CACHE_HASHED_BIT &&
32454+
(max_allowed_join_cache_level > JOIN_CACHE_HASHED_BIT ||
32455+
hint_table_state(thd, table, BNL_HINT_ENUM, false) ||
32456+
hint_table_state(thd, table, BKA_HINT_ENUM, false));
32457+
}
3244832458

3244932459
/**
3245032460
Save a query execution plan so that the caller can revert to it if needed,

sql/sql_select.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1885,11 +1885,7 @@ class JOIN :public Sql_alloc
18851885
ulonglong curr_space,
18861886
ulonglong needed_space);
18871887
void set_allowed_join_cache_types();
1888-
bool is_allowed_hash_join_access()
1889-
{
1890-
return MY_TEST(allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
1891-
max_allowed_join_cache_level > JOIN_CACHE_HASHED_BIT;
1892-
}
1888+
bool is_allowed_hash_join_access(const TABLE *table);
18931889
/*
18941890
Check if we need to create a temporary table.
18951891
This has to be done if all tables are not already read (const tables)

0 commit comments

Comments
 (0)