Skip to content

Commit

Permalink
Move join->emb_smj_nest setting to choose_plan()
Browse files Browse the repository at this point in the history
This cleans up the interface for choose_plan() as it is not depending
on setting join->emb_sj_nest.

choose_plan() now sets up join->emb_sj_nest and join->allowed_tables before
calling optimize_straight_join() and best_extension_by_limited_search().

Other things:
- Converted some 'if' to DBUG_ASSERT() as these should always be true.
- Calculate 'allowed_tables' in choose_plan() as this never changes in
  the childs.
- Added assert to check that next_emb->nested_join->n_tables doesn't
  get to a wrong value.
- Documented some variables in sql_select.h
  • Loading branch information
montywi authored and spetrunia committed Feb 2, 2023
1 parent 249475b commit 1d82e5d
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
2 changes: 1 addition & 1 deletion sql/opt_split.cc
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,7 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(double record_count,
table_map all_table_map= (((table_map) 1) << join->table_count) - 1;
reset_validity_vars_for_keyuses(best_key_keyuse_ext_start, best_table,
best_key, remaining_tables, true);
choose_plan(join, all_table_map & ~join->const_table_map);
choose_plan(join, all_table_map & ~join->const_table_map, 0);

/*
Check that the chosen plan is really a splitting plan.
Expand Down
4 changes: 1 addition & 3 deletions sql/opt_subselect.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2500,8 +2500,7 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
!sj_nest->sj_subq_pred->is_correlated &&
sj_nest->sj_subq_pred->types_allow_materialization)
{
join->emb_sjm_nest= sj_nest;
if (choose_plan(join, all_table_map &~join->const_table_map))
if (choose_plan(join, all_table_map &~join->const_table_map, sj_nest))
DBUG_RETURN(TRUE); /* purecov: inspected */
/*
The best plan to run the subquery is now in join->best_positions,
Expand Down Expand Up @@ -2594,7 +2593,6 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
}
}
}
join->emb_sjm_nest= NULL;
DBUG_RETURN(FALSE);
}

Expand Down
39 changes: 26 additions & 13 deletions sql/sql_select.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6035,7 +6035,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
/* Find an optimal join order of the non-constant tables. */
if (join->const_tables != join->table_count)
{
if (choose_plan(join, all_table_map & ~join->const_table_map))
if (choose_plan(join, all_table_map & ~join->const_table_map, 0))
goto error;

#ifdef HAVE_valgrind
Expand Down Expand Up @@ -9238,6 +9238,7 @@ static void choose_initial_table_order(JOIN *join)
@param join pointer to the structure providing all context info for
the query
@param join_tables set of the tables in the query
@param emb_sjm_nest List of tables in case of materialized semi-join nest

@retval
FALSE ok
Expand All @@ -9246,28 +9247,35 @@ static void choose_initial_table_order(JOIN *join)
*/

bool
choose_plan(JOIN *join, table_map join_tables)
choose_plan(JOIN *join, table_map join_tables, TABLE_LIST *emb_sjm_nest)
{
uint search_depth= join->thd->variables.optimizer_search_depth;
uint use_cond_selectivity=
join->thd->variables.optimizer_use_condition_selectivity;
bool straight_join= MY_TEST(join->select_options & SELECT_STRAIGHT_JOIN);
THD *thd= join->thd;
qsort2_cmp jtab_sort_func;
DBUG_ENTER("choose_plan");

join->cur_embedding_map= 0;
join->extra_heuristic_pruning= false;
join->prune_level= join->thd->variables.optimizer_prune_level;

reset_nj_counters(join, join->join_list);
qsort2_cmp jtab_sort_func;

if (join->emb_sjm_nest)
if ((join->emb_sjm_nest= emb_sjm_nest))
{
/* We're optimizing semi-join materialization nest, so put the
tables from this semi-join as first
*/
jtab_sort_func= join_tab_cmp_embedded_first;
/*
If we are searching for the execution plan of a materialized semi-join
nest then allowed_tables contains bits only for the tables from this
nest.
*/
join->allowed_tables= (emb_sjm_nest->sj_inner_tables &
~join->const_table_map);
}
else
{
Expand All @@ -9280,6 +9288,7 @@ choose_plan(JOIN *join, table_map join_tables)
of records accessed.
*/
jtab_sort_func= straight_join ? join_tab_cmp_straight : join_tab_cmp;
join->allowed_tables= ~join->const_table_map;
}

/*
Expand All @@ -9290,19 +9299,19 @@ choose_plan(JOIN *join, table_map join_tables)
*/
my_qsort2(join->best_ref + join->const_tables,
join->table_count - join->const_tables, sizeof(JOIN_TAB*),
jtab_sort_func, (void*)join->emb_sjm_nest);
jtab_sort_func, (void*) emb_sjm_nest);

Json_writer_object wrapper(thd);
Json_writer_array trace_plan(thd,"considered_execution_plans");

if (!join->emb_sjm_nest)
{
if (!emb_sjm_nest)
choose_initial_table_order(join);
}

/*
Note: constant tables are already in the join prefix. We don't
put them into the cur_sj_inner_tables, though.
*/

join->cur_sj_inner_tables= 0;

if (straight_join)
Expand Down Expand Up @@ -9334,6 +9343,8 @@ choose_plan(JOIN *join, table_map join_tables)
*/
if (join->thd->lex->is_single_level_stmt())
join->thd->status_var.last_query_cost= join->best_read;

join->emb_sjm_nest= 0;
DBUG_RETURN(FALSE);
}

Expand Down Expand Up @@ -9728,6 +9739,7 @@ greedy_search(JOIN *join,
// ==join->tables or # tables in the sj-mat nest we're optimizing
uint n_tables __attribute__((unused));
DBUG_ENTER("greedy_search");
DBUG_ASSERT(!(remaining_tables & join->const_table_map));

/* number of tables that remain to be optimized */
usable_tables= (join->emb_sjm_nest ?
Expand Down Expand Up @@ -10716,7 +10728,6 @@ best_extension_by_limited_search(JOIN *join,
/*
allowed_tables is used to check if there are tables left that can improve
a key search and to see if there are more tables to add in next iteration.

allowed_current_tables tells us which tables we can add to the current
plan at this stage.
*/
Expand Down Expand Up @@ -10880,7 +10891,7 @@ best_extension_by_limited_search(JOIN *join,
*/
if (best_record_count >= current_record_count &&
best_read_time >= current_read_time &&
(!(position->key_dependent & allowed_tables) ||
(!(position->key_dependent & join->allowed_tables) ||
position->records_read < 2.0))
{
best_record_count= current_record_count;
Expand Down Expand Up @@ -10944,7 +10955,7 @@ best_extension_by_limited_search(JOIN *join,
.add("estimated_join_cardinality", partial_join_cardinality);

if (search_depth > 1 &&
((remaining_tables & ~real_table_bit) & allowed_tables))
((remaining_tables & ~real_table_bit) & join->allowed_tables))

{
/* Recursively expand the current partial plan */
Expand Down Expand Up @@ -18299,10 +18310,12 @@ static bool check_interleaving_with_nj(JOIN_TAB *next_tab)
join->cur_embedding_map |= next_emb->nested_join->nj_map;
}

DBUG_ASSERT(next_emb->nested_join->n_tables >=
next_emb->nested_join->counter);

if (next_emb->nested_join->n_tables !=
next_emb->nested_join->counter)
break;

/*
We're currently at Y or Z-bracket as depicted in the above picture.
Mark that we've left it and continue walking up the brackets hierarchy.
Expand Down Expand Up @@ -29869,7 +29882,7 @@ JOIN::reoptimize(Item *added_where, table_map join_tables,
return REOPT_ERROR;

/* Re-run the join optimizer to compute a new query plan. */
if (choose_plan(this, join_tables))
if (choose_plan(this, join_tables, 0))
return REOPT_ERROR;

return REOPT_NEW_PLAN;
Expand Down
27 changes: 25 additions & 2 deletions sql/sql_select.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,23 @@ typedef struct st_join_table {
double cached_scan_time;
double cached_scan_and_compare_time;

table_map dependent,key_dependent;
/*
dependent is the table that must be read before the current one
Used for example with STRAIGHT_JOIN or outer joins
*/
table_map dependent;
/*
key_dependent is dependent but add those tables that are used to compare
with a key field in a simple expression. See add_key_field().
It is only used to prune searches in best_extension_by_limited_search()
*/
table_map key_dependent;
/*
Tables that have expression in their attached condition clause that depends
on this table.
*/
table_map related_tables;

/*
Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra'
column, or 0 if there is no info.
Expand Down Expand Up @@ -1256,6 +1272,13 @@ class JOIN :public Sql_alloc
bool hash_join;
bool do_send_rows;
table_map const_table_map;

/*
Tables one is allowed to use in choose_plan(). Either all or
set to a mapt of the tables in the materialized semi-join nest
*/
table_map allowed_tables;

/**
Bitmap of semijoin tables that the current partial plan decided
to materialize and access by lookups
Expand Down Expand Up @@ -2370,7 +2393,7 @@ inline Item * or_items(THD *thd, Item* cond, Item *item)
{
return (cond ? (new (thd->mem_root) Item_cond_or(thd, cond, item)) : item);
}
bool choose_plan(JOIN *join, table_map join_tables);
bool choose_plan(JOIN *join, table_map join_tables, TABLE_LIST *emb_sjm_nest);
void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
table_map last_remaining_tables,
bool first_alt, uint no_jbuf_before,
Expand Down

0 comments on commit 1d82e5d

Please sign in to comment.