1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

Merge tsmith@bk-internal.mysql.com:/home/bk/mysql-5.1

into  quadxeon.mysql.com:/benchmarks/ext3/TOSAVE/tsmith/bk/maint/jun05/51
This commit is contained in:
tsmith@quadxeon.mysql.com
2007-06-05 23:06:43 +02:00
98 changed files with 2219 additions and 734 deletions

View File

@ -49,15 +49,15 @@ static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
table_map used_tables);
static void choose_plan(JOIN *join,table_map join_tables);
static bool choose_plan(JOIN *join,table_map join_tables);
static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd,
table_map remaining_tables, uint idx,
double record_count, double read_time);
static void optimize_straight_join(JOIN *join, table_map join_tables);
static void greedy_search(JOIN *join, table_map remaining_tables,
static bool greedy_search(JOIN *join, table_map remaining_tables,
uint depth, uint prune_level);
static void best_extension_by_limited_search(JOIN *join,
static bool best_extension_by_limited_search(JOIN *join,
table_map remaining_tables,
uint idx, double record_count,
double read_time, uint depth,
@ -69,7 +69,7 @@ static int join_tab_cmp_straight(const void* ptr1, const void* ptr2);
TODO: 'find_best' is here only temporarily until 'greedy_search' is
tested and approved.
*/
static void find_best(JOIN *join,table_map rest_tables,uint index,
static bool find_best(JOIN *join,table_map rest_tables,uint index,
double record_count,double read_time);
static uint cache_record_length(JOIN *join,uint index);
static double prev_record_reads(JOIN *join, uint idx, table_map found_ref);
@ -2104,6 +2104,17 @@ JOIN::exec()
thd->examined_row_count+= curr_join->examined_rows;
DBUG_PRINT("counts", ("thd->examined_row_count: %lu",
(ulong) thd->examined_row_count));
/*
With EXPLAIN EXTENDED we have to restore original ref_array
for a derived table which is always materialized.
Otherwise we would not be able to print the query correctly.
*/
if (items0 &&
(thd->lex->describe & DESCRIBE_EXTENDED) &&
select_lex->linkage == DERIVED_TABLE_TYPE)
set_items_ref_array(items0);
DBUG_VOID_RETURN;
}
@ -2755,7 +2766,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if (join->const_tables != join->tables)
{
optimize_keyuse(join, keyuse_array);
choose_plan(join, all_table_map & ~join->const_table_map);
if (choose_plan(join, all_table_map & ~join->const_table_map))
DBUG_RETURN(TRUE);
}
else
{
@ -4404,11 +4416,12 @@ best_access_path(JOIN *join,
the array 'join->best_positions', and the cost of the plan in
'join->best_read'.
RETURN
None
RETURN VALUES
FALSE ok
TRUE Fatal error
*/
static void
static bool
choose_plan(JOIN *join, table_map join_tables)
{
uint search_depth= join->thd->variables.optimizer_search_depth;
@ -4441,14 +4454,16 @@ choose_plan(JOIN *join, table_map join_tables)
the greedy version. Will be removed when greedy_search is approved.
*/
join->best_read= DBL_MAX;
find_best(join, join_tables, join->const_tables, 1.0, 0.0);
if (find_best(join, join_tables, join->const_tables, 1.0, 0.0))
DBUG_RETURN(TRUE);
}
else
{
if (search_depth == 0)
/* Automatically determine a reasonable value for 'search_depth' */
search_depth= determine_search_depth(join);
greedy_search(join, join_tables, search_depth, prune_level);
if (greedy_search(join, join_tables, search_depth, prune_level))
DBUG_RETURN(TRUE);
}
}
@ -4456,7 +4471,7 @@ choose_plan(JOIN *join, table_map join_tables)
Store the cost of this query into a user variable
*/
join->thd->status_var.last_query_cost= join->best_read;
DBUG_VOID_RETURN;
DBUG_RETURN(FALSE);
}
@ -4684,11 +4699,12 @@ optimize_straight_join(JOIN *join, table_map join_tables)
In the future, 'greedy_search' might be extended to support other
implementations of 'best_extension', e.g. some simpler quadratic procedure.
RETURN
None
RETURN VALUES
FALSE ok
TRUE Fatal error
*/
static void
static bool
greedy_search(JOIN *join,
table_map remaining_tables,
uint search_depth,
@ -4710,8 +4726,9 @@ greedy_search(JOIN *join,
do {
/* Find the extension of the current QEP with the lowest cost */
join->best_read= DBL_MAX;
best_extension_by_limited_search(join, remaining_tables, idx, record_count,
read_time, search_depth, prune_level);
if (best_extension_by_limited_search(join, remaining_tables, idx, record_count,
read_time, search_depth, prune_level))
DBUG_RETURN(TRUE);
if (size_remain <= search_depth)
{
@ -4722,7 +4739,7 @@ greedy_search(JOIN *join,
DBUG_EXECUTE("opt", print_plan(join, join->tables,
record_count, read_time, read_time,
"optimal"););
DBUG_VOID_RETURN;
DBUG_RETURN(FALSE);
}
/* select the first table in the optimal extension as most promising */
@ -4867,11 +4884,12 @@ greedy_search(JOIN *join,
The parameter 'search_depth' provides control over the recursion
depth, and thus the size of the resulting optimal plan.
RETURN
None
RETURN VALUES
FALSE ok
TRUE Fatal error
*/
static void
static bool
best_extension_by_limited_search(JOIN *join,
table_map remaining_tables,
uint idx,
@ -4880,11 +4898,12 @@ best_extension_by_limited_search(JOIN *join,
uint search_depth,
uint prune_level)
{
DBUG_ENTER("best_extension_by_limited_search");
THD *thd= join->thd;
if (thd->killed) // Abort
return;
DBUG_RETURN(TRUE);
DBUG_ENTER("best_extension_by_limited_search");
DBUG_EXECUTE("opt", print_plan(join, idx, read_time, record_count, idx,
"SOFAR:"););
@ -4966,15 +4985,14 @@ best_extension_by_limited_search(JOIN *join,
if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) )
{ /* Recursively expand the current partial plan */
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
best_extension_by_limited_search(join,
remaining_tables & ~real_table_bit,
idx + 1,
current_record_count,
current_read_time,
search_depth - 1,
prune_level);
if (thd->killed)
DBUG_VOID_RETURN;
if (best_extension_by_limited_search(join,
remaining_tables & ~real_table_bit,
idx + 1,
current_record_count,
current_read_time,
search_depth - 1,
prune_level))
DBUG_RETURN(TRUE);
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
}
else
@ -5003,19 +5021,26 @@ best_extension_by_limited_search(JOIN *join,
restore_prev_nj_state(s);
}
}
DBUG_VOID_RETURN;
DBUG_RETURN(FALSE);
}
/*
TODO: this function is here only temporarily until 'greedy_search' is
tested and accepted.
RETURN VALUES
FALSE ok
TRUE Fatal error
*/
static void
static bool
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
double read_time)
{
DBUG_ENTER("find_best");
THD *thd= join->thd;
if (thd->killed)
DBUG_RETURN(TRUE);
if (!rest_tables)
{
DBUG_PRINT("best",("read_time: %g record_count: %g",read_time,
@ -5032,10 +5057,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
sizeof(POSITION)*idx);
join->best_read= read_time - 0.001;
}
return;
DBUG_RETURN(FALSE);
}
if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read)
return; /* Found better before */
DBUG_RETURN(FALSE); /* Found better before */
JOIN_TAB *s;
double best_record_count=DBL_MAX,best_read_time=DBL_MAX;
@ -5068,10 +5093,9 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
best_read_time=current_read_time;
}
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
find_best(join,rest_tables & ~real_table_bit,idx+1,
current_record_count,current_read_time);
if (thd->killed)
return;
if (find_best(join,rest_tables & ~real_table_bit,idx+1,
current_record_count,current_read_time))
DBUG_RETURN(TRUE);
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
}
restore_prev_nj_state(s);
@ -5079,6 +5103,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
break; // Don't test all combinations
}
}
DBUG_RETURN(FALSE);
}
@ -6099,13 +6124,39 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
}
/*
Push down all predicates from on expressions.
Each of these predicated are guarded by a variable
Push down conditions from all on expressions.
Each of these conditions are guarded by a variable
that turns if off just before null complemented row for
outer joins is formed. Thus, the predicates from an
outer joins is formed. Thus, the condition from an
'on expression' are guaranteed not to be checked for
the null complemented row.
*/
/* First push down constant conditions from on expressions */
for (JOIN_TAB *join_tab= join->join_tab+join->const_tables;
join_tab < join->join_tab+join->tables ; join_tab++)
{
if (*join_tab->on_expr_ref)
{
JOIN_TAB *cond_tab= join_tab->first_inner;
COND *tmp= make_cond_for_table(*join_tab->on_expr_ref,
join->const_table_map,
(table_map) 0);
if (!tmp)
continue;
tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl);
if (!tmp)
DBUG_RETURN(1);
tmp->quick_fix_field();
cond_tab->select_cond= !cond_tab->select_cond ? tmp :
new Item_cond_and(cond_tab->select_cond,tmp);
if (!cond_tab->select_cond)
DBUG_RETURN(1);
cond_tab->select_cond->quick_fix_field();
}
}
/* Push down non-constant conditions from on expressions */
JOIN_TAB *last_tab= tab;
while (first_inner_tab && first_inner_tab->last_inner == last_tab)
{
@ -6553,7 +6604,6 @@ void JOIN::cleanup(bool full)
for (tab= join_tab, end= tab+tables; tab != end; tab++)
tab->cleanup();
table= 0;
tables= 0;
}
else
{
@ -8992,7 +9042,7 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field,
Make sure that the blob fits into a Field_varstring which has
2-byte lenght.
*/
if (convert_blob_length && convert_blob_length < UINT_MAX16 &&
if (convert_blob_length && convert_blob_length <= Field_varstring::MAX_SIZE &&
(org_field->flags & BLOB_FLAG))
new_field= new Field_varstring(convert_blob_length,
org_field->maybe_null(),
@ -9060,8 +9110,13 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
item->name, item->decimals, TRUE);
break;
case INT_RESULT:
/* Select an integer type with the minimal fit precision */
if (item->max_length > MY_INT32_NUM_DECIMAL_DIGITS)
/*
Select an integer type with the minimal fit precision.
MY_INT32_NUM_DECIMAL_DIGITS is sign inclusive, don't consider the sign.
Values with MY_INT32_NUM_DECIMAL_DIGITS digits may or may not fit into
Field_long : make them Field_longlong.
*/
if (item->max_length >= (MY_INT32_NUM_DECIMAL_DIGITS - 1))
new_field=new Field_longlong(item->max_length, maybe_null,
item->name, item->unsigned_flag);
else
@ -9085,7 +9140,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
2-byte lenght.
*/
else if (item->max_length/item->collation.collation->mbmaxlen > 255 &&
convert_blob_length < UINT_MAX16 && convert_blob_length)
convert_blob_length <= Field_varstring::MAX_SIZE &&
convert_blob_length)
new_field= new Field_varstring(convert_blob_length, maybe_null,
item->name, table->s,
item->collation.collation);
@ -15531,8 +15587,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
break;
}
}
if (tab->next_select == sub_select_cache)
extra.append(STRING_WITH_LEN("; Using join cache"));
if (i > 0 && tab[-1].next_select == sub_select_cache)
extra.append(STRING_WITH_LEN("; Using join buffer"));
/* Skip initial "; "*/
const char *str= extra.ptr();