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) ...@@ -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_where || in_to_exists_where->fixed);
DBUG_ASSERT(!in_to_exists_having || in_to_exists_having->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 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, ...@@ -3046,12 +3046,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
key_map const_ref, eq_part; key_map const_ref, eq_part;
bool has_expensive_keyparts; bool has_expensive_keyparts;
TABLE **table_vector; 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; KEYUSE *keyuse,*start_keyuse;
table_map outer_join=0; table_map outer_join=0;
table_map no_rows_const_tables= 0; table_map no_rows_const_tables= 0;
SARGABLE_PARAM *sargables= 0; SARGABLE_PARAM *sargables= 0;
JOIN_TAB *stat_vector[MAX_TABLES+1];
List_iterator<TABLE_LIST> ti(tables_list); List_iterator<TABLE_LIST> ti(tables_list);
TABLE_LIST *tables; TABLE_LIST *tables;
DBUG_ENTER("make_join_statistics"); DBUG_ENTER("make_join_statistics");
...@@ -3060,9 +3059,19 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, ...@@ -3060,9 +3059,19 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
table_count=join->table_count; table_count=join->table_count;
stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*(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)); 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 */ DBUG_RETURN(1); // Eom /* purecov: inspected */
join->best_ref=stat_vector; join->best_ref=stat_vector;
...@@ -15927,7 +15936,8 @@ join_read_system(JOIN_TAB *tab) ...@@ -15927,7 +15936,8 @@ join_read_system(JOIN_TAB *tab)
empty_record(table); // Make empty record empty_record(table); // Make empty record
return -1; return -1;
} }
update_virtual_fields(tab->join->thd, table); if (table->vfield)
update_virtual_fields(tab->join->thd, table);
store_record(table,record[1]); store_record(table,record[1]);
} }
else if (!table->status) // Only happens with left join else if (!table->status) // Only happens with left join
...@@ -15976,7 +15986,8 @@ join_read_const(JOIN_TAB *tab) ...@@ -15976,7 +15986,8 @@ join_read_const(JOIN_TAB *tab)
return report_error(table, error); return report_error(table, error);
return -1; return -1;
} }
update_virtual_fields(tab->join->thd, table); if (table->vfield)
update_virtual_fields(tab->join->thd, table);
store_record(table,record[1]); store_record(table,record[1]);
} }
else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join 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 ...@@ -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 Information about a position of table within a join order. Used in join
optimization. optimization.
*/ */
typedef struct st_position typedef struct st_position :public Sql_alloc
{ {
/* The table that's put into join order */ /* The table that's put into join order */
JOIN_TAB *table; JOIN_TAB *table;
...@@ -844,23 +844,36 @@ class JOIN :public Sql_alloc ...@@ -844,23 +844,36 @@ class JOIN :public Sql_alloc
*/ */
class Join_plan_state { class Join_plan_state {
public: public:
DYNAMIC_ARRAY keyuse; /* Copy of the JOIN::keyuse array. */ DYNAMIC_ARRAY keyuse; /* Copy of the JOIN::keyuse array. */
POSITION best_positions[MAX_TABLES+1]; /* Copy of JOIN::best_positions */ POSITION *best_positions; /* Copy of JOIN::best_positions */
/* Copies of the JOIN_TAB::keyuse pointers for each JOIN_TAB. */ /* 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. */ /* Copies of JOIN_TAB::checked_keys for each JOIN_TAB. */
key_map join_tab_checked_keys[MAX_TABLES]; key_map *join_tab_checked_keys;
SJ_MATERIALIZATION_INFO *sj_mat_info[MAX_TABLES]; SJ_MATERIALIZATION_INFO **sj_mat_info;
my_bool error;
public: public:
Join_plan_state() Join_plan_state(uint tables) : error(0)
{ {
keyuse.elements= 0; keyuse.elements= 0;
keyuse.buffer= NULL; 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(JOIN *join);
~Join_plan_state() ~Join_plan_state()
{ {
delete_dynamic(&keyuse); delete_dynamic(&keyuse);
my_free(best_positions, MYF(0));
} }
}; };
...@@ -961,7 +974,7 @@ class JOIN :public Sql_alloc ...@@ -961,7 +974,7 @@ class JOIN :public Sql_alloc
*/ */
ha_rows fetch_limit; ha_rows fetch_limit;
/* Finally picked QEP. This is result of join optimization */ /* Finally picked QEP. This is result of join optimization */
POSITION best_positions[MAX_TABLES+1]; POSITION *best_positions;
/******* Join optimization state members start *******/ /******* Join optimization state members start *******/
/* /*
...@@ -971,7 +984,7 @@ class JOIN :public Sql_alloc ...@@ -971,7 +984,7 @@ class JOIN :public Sql_alloc
TABLE_LIST *emb_sjm_nest; TABLE_LIST *emb_sjm_nest;
/* Current join optimization state */ /* Current join optimization state */
POSITION positions[MAX_TABLES+1]; POSITION *positions;
/* /*
Bitmap of nested joins embedding the position at the end of the current Bitmap of nested joins embedding the position at the end of the current
...@@ -1241,6 +1254,7 @@ class JOIN :public Sql_alloc ...@@ -1241,6 +1254,7 @@ class JOIN :public Sql_alloc
exec_const_cond= 0; exec_const_cond= 0;
group_optimized_away= 0; group_optimized_away= 0;
no_rows_in_result_called= 0; no_rows_in_result_called= 0;
positions= best_positions= 0;
all_fields= fields_arg; all_fields= fields_arg;
if (&fields_list != &fields_arg) /* Avoid valgrind-warning */ 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