Commit 8e825a22 authored by Michael Widenius's avatar Michael Widenius

Fixes lp:941889 "JOIN constructors takes a long time in 5.3"

- Remove all references of MAX_TABLES from JOIN struct and make these dynamic
- Updated Join_plan_state to allocate just as many elements as it's needed


sql/opt_subselect.cc:
  Optimized version of Join_plan_state
sql/sql_select.cc:
  Set join->positions and join->best_positions dynamicly
  Don't call update_virtual_fields() if table->vfield is not set.
sql/sql_select.h:
  Remove all references of MAX_TABLES from JOIN struct and Join_plan_state and make these dynamic
parent de1765fb
......@@ -4961,7 +4961,8 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
DBUG_ASSERT(!in_to_exists_where || in_to_exists_where->fixed);
DBUG_ASSERT(!in_to_exists_having || in_to_exists_having->fixed);
Join_plan_state save_qep; /* The original QEP of the subquery. */
/* The original QEP of the subquery. */
Join_plan_state save_qep(table_count);
/*
Compute and compare the costs of materialization and in-exists if both
......
......@@ -3046,12 +3046,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
key_map const_ref, eq_part;
bool has_expensive_keyparts;
TABLE **table_vector;
JOIN_TAB *stat,*stat_end,*s,**stat_ref;
JOIN_TAB *stat,*stat_end,*s,**stat_ref, **stat_vector;
KEYUSE *keyuse,*start_keyuse;
table_map outer_join=0;
table_map no_rows_const_tables= 0;
SARGABLE_PARAM *sargables= 0;
JOIN_TAB *stat_vector[MAX_TABLES+1];
List_iterator<TABLE_LIST> ti(tables_list);
TABLE_LIST *tables;
DBUG_ENTER("make_join_statistics");
......@@ -3060,9 +3059,19 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
table_count=join->table_count;
stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*(table_count));
stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES);
stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*
(MAX_TABLES + table_count + 1));
stat_vector= stat_ref + MAX_TABLES;
table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2));
if (!stat || !stat_ref || !table_vector)
join->positions= new (join->thd->mem_root) POSITION[(table_count+1)];
/*
best_positions is ok to allocate with alloc() as we copy things to it with
memcpy()
*/
join->best_positions= (POSITION*) join->thd->alloc(sizeof(POSITION)*
(table_count +1));
if (join->thd->is_fatal_error)
DBUG_RETURN(1); // Eom /* purecov: inspected */
join->best_ref=stat_vector;
......@@ -15927,7 +15936,8 @@ join_read_system(JOIN_TAB *tab)
empty_record(table); // Make empty record
return -1;
}
update_virtual_fields(tab->join->thd, table);
if (table->vfield)
update_virtual_fields(tab->join->thd, table);
store_record(table,record[1]);
}
else if (!table->status) // Only happens with left join
......@@ -15976,7 +15986,8 @@ join_read_const(JOIN_TAB *tab)
return report_error(table, error);
return -1;
}
update_virtual_fields(tab->join->thd, table);
if (table->vfield)
update_virtual_fields(tab->join->thd, table);
store_record(table,record[1]);
}
else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join
......
......@@ -742,7 +742,7 @@ class Sj_materialization_picker : public Semi_join_strategy_picker
Information about a position of table within a join order. Used in join
optimization.
*/
typedef struct st_position
typedef struct st_position :public Sql_alloc
{
/* The table that's put into join order */
JOIN_TAB *table;
......@@ -844,23 +844,36 @@ class JOIN :public Sql_alloc
*/
class Join_plan_state {
public:
DYNAMIC_ARRAY keyuse; /* Copy of the JOIN::keyuse array. */
POSITION best_positions[MAX_TABLES+1]; /* Copy of JOIN::best_positions */
DYNAMIC_ARRAY keyuse; /* Copy of the JOIN::keyuse array. */
POSITION *best_positions; /* Copy of JOIN::best_positions */
/* Copies of the JOIN_TAB::keyuse pointers for each JOIN_TAB. */
KEYUSE *join_tab_keyuse[MAX_TABLES];
KEYUSE **join_tab_keyuse;
/* Copies of JOIN_TAB::checked_keys for each JOIN_TAB. */
key_map join_tab_checked_keys[MAX_TABLES];
SJ_MATERIALIZATION_INFO *sj_mat_info[MAX_TABLES];
key_map *join_tab_checked_keys;
SJ_MATERIALIZATION_INFO **sj_mat_info;
my_bool error;
public:
Join_plan_state()
Join_plan_state(uint tables) : error(0)
{
keyuse.elements= 0;
keyuse.buffer= NULL;
best_positions= 0; /* To detect errors */
error= my_multi_malloc(MYF(MY_WME),
&best_positions,
sizeof(*best_positions) * (tables + 1),
&join_tab_keyuse,
sizeof(*join_tab_keyuse) * tables,
&join_tab_checked_keys,
sizeof(*join_tab_checked_keys) * tables,
&sj_mat_info,
sizeof(sj_mat_info) * tables,
NullS) == 0;
}
Join_plan_state(JOIN *join);
~Join_plan_state()
{
delete_dynamic(&keyuse);
my_free(best_positions, MYF(0));
}
};
......@@ -961,7 +974,7 @@ class JOIN :public Sql_alloc
*/
ha_rows fetch_limit;
/* Finally picked QEP. This is result of join optimization */
POSITION best_positions[MAX_TABLES+1];
POSITION *best_positions;
/******* Join optimization state members start *******/
/*
......@@ -971,7 +984,7 @@ class JOIN :public Sql_alloc
TABLE_LIST *emb_sjm_nest;
/* Current join optimization state */
POSITION positions[MAX_TABLES+1];
POSITION *positions;
/*
Bitmap of nested joins embedding the position at the end of the current
......@@ -1241,6 +1254,7 @@ class JOIN :public Sql_alloc
exec_const_cond= 0;
group_optimized_away= 0;
no_rows_in_result_called= 0;
positions= best_positions= 0;
all_fields= fields_arg;
if (&fields_list != &fields_arg) /* Avoid valgrind-warning */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment