1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge 5.5-main -> 5.5-show-explain

This commit is contained in:
Sergey Petrunya
2012-07-25 20:53:49 +04:00
702 changed files with 44791 additions and 2591 deletions

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates.
2009-2011 Monty Program Ab
/* Copyright (c) 2000, 2012 Oracle and/or its affiliates.
Copyright (c) 2009, 2012, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -271,6 +271,8 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
bool *inherited_fl);
JOIN_TAB *first_depth_first_tab(JOIN* join);
JOIN_TAB *next_depth_first_tab(JOIN* join, JOIN_TAB* tab);
JOIN_TAB *first_breadth_first_tab(JOIN *join);
JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab);
#ifndef DBUG_OFF
@ -1045,7 +1047,10 @@ JOIN::optimize_inner()
}
eval_select_list_used_tables();
if (optimize_constant_subqueries())
DBUG_RETURN(1);
table_count= select_lex->leaf_tables.elements;
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
@ -1332,6 +1337,12 @@ JOIN::optimize_inner()
{
conds= substitute_for_best_equal_field(NO_PARTICULAR_TAB, conds,
cond_equal, map2table);
if (thd->is_error())
{
error= 1;
DBUG_PRINT("error",("Error from substitute_for_best_equal"));
DBUG_RETURN(1);
}
conds->update_used_tables();
DBUG_EXECUTE("where",
print_where(conds,
@ -1352,6 +1363,12 @@ JOIN::optimize_inner()
*tab->on_expr_ref,
tab->cond_equal,
map2table);
if (thd->is_error())
{
error= 1;
DBUG_PRINT("error",("Error from substitute_for_best_equal"));
DBUG_RETURN(1);
}
(*tab->on_expr_ref)->update_used_tables();
}
}
@ -6702,6 +6719,32 @@ void JOIN::get_prefix_cost_and_fanout(uint n_tables,
}
/**
Estimate the number of rows that query execution will read.
@todo This is a very pessimistic upper bound. Use join selectivity
when available to produce a more realistic number.
*/
double JOIN::get_examined_rows()
{
ha_rows examined_rows;
double prev_fanout= 1;
JOIN_TAB *tab= first_breadth_first_tab(this);
JOIN_TAB *prev_tab= tab;
examined_rows= tab->get_examined_rows();
while ((tab= next_breadth_first_tab(this, tab)))
{
prev_fanout *= prev_tab->records_read;
examined_rows+= tab->get_examined_rows() * prev_fanout;
prev_tab= tab;
}
return examined_rows;
}
/**
Find a good, possibly optimal, query execution plan (QEP) by a possibly
exhaustive search.
@ -8174,36 +8217,15 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
row_limit= unit->select_limit_cnt;
do_send_rows= row_limit ? 1 : 0;
join_tab->use_join_cache= FALSE;
join_tab->cache=0; /* No caching */
bzero(join_tab, sizeof(JOIN_TAB));
join_tab->table=temp_table;
join_tab->cache_select= 0;
join_tab->select=0;
join_tab->select_cond= 0; // Avoid valgrind warning
join_tab->set_select_cond(NULL, __LINE__);
join_tab->quick=0;
join_tab->type= JT_ALL; /* Map through all records */
join_tab->keys.init();
join_tab->keys.set_all(); /* test everything in quick */
join_tab->info=0;
join_tab->on_expr_ref=0;
join_tab->last_inner= 0;
join_tab->first_unmatched= 0;
join_tab->ref.key = -1;
join_tab->not_used_in_distinct=0;
join_tab->read_first_record= join_init_read_record;
join_tab->preread_init_done= FALSE;
join_tab->join= this;
join_tab->ref.key_parts= 0;
join_tab->keep_current_rowid= FALSE;
join_tab->flush_weedout_table= join_tab->check_weed_out_table= NULL;
join_tab->do_firstmatch= NULL;
join_tab->loosescan_match_tab= NULL;
join_tab->emb_sj_nest= NULL;
join_tab->pre_idx_push_select_cond= NULL;
join_tab->bush_root_tab= NULL;
join_tab->bush_children= NULL;
join_tab->last_leaf_in_bush= FALSE;
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
temp_table->status=0;
temp_table->null_row=0;
@ -10401,6 +10423,51 @@ double JOIN_TAB::scan_time()
return res;
}
/**
Estimate the number of rows that a an access method will read from a table.
@todo: why not use JOIN_TAB::found_records
*/
ha_rows JOIN_TAB::get_examined_rows()
{
ha_rows examined_rows;
if (select && select->quick)
examined_rows= select->quick->records;
else if (type == JT_NEXT || type == JT_ALL ||
type == JT_HASH || type ==JT_HASH_NEXT)
{
if (limit)
{
/*
@todo This estimate is wrong, a LIMIT query may examine much more rows
than the LIMIT itself.
*/
examined_rows= limit;
}
else
{
if (table->is_filled_at_execution())
examined_rows= records;
else
{
/*
handler->info(HA_STATUS_VARIABLE) has been called in
make_join_statistics()
*/
examined_rows= table->file->stats.records;
}
}
}
else
examined_rows= (ha_rows) records_read;
return examined_rows;
}
/**
Initialize the join_tab before reading.
Currently only derived table/view materialization is done here.
@ -10718,6 +10785,22 @@ void JOIN::cleanup(bool full)
tmp_join->tmp_table_param.save_copy_field= 0;
}
tmp_table_param.cleanup();
if (!join_tab)
{
List_iterator<TABLE_LIST> li(*join_list);
TABLE_LIST *table_ref;
while ((table_ref= li++))
{
if (table_ref->table &&
table_ref->jtbm_subselect &&
table_ref->jtbm_subselect->is_jtbm_const_tab)
{
free_tmp_table(thd, table_ref->table);
table_ref->table= NULL;
}
}
}
}
DBUG_VOID_RETURN;
}
@ -11394,9 +11477,9 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
if (!item)
{
Item_func_eq *eq_item;
if ((eq_item= new Item_func_eq(orig_left_item, orig_right_item)))
if (!(eq_item= new Item_func_eq(orig_left_item, orig_right_item)) ||
eq_item->set_cmp_func())
return FALSE;
eq_item->set_cmp_func();
eq_item->quick_fix_field();
item= eq_item;
}
@ -11489,9 +11572,9 @@ static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row,
if (!is_converted)
{
Item_func_eq *eq_item;
if (!(eq_item= new Item_func_eq(left_item, right_item)))
if (!(eq_item= new Item_func_eq(left_item, right_item)) ||
eq_item->set_cmp_func())
return FALSE;
eq_item->set_cmp_func();
eq_item->quick_fix_field();
eq_list->push_back(eq_item);
}
@ -12177,9 +12260,8 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
eq_item= new Item_func_eq(field_item->real_item(), head_item);
if (!eq_item)
if (!eq_item || eq_item->set_cmp_func())
return 0;
eq_item->set_cmp_func();
eq_item->quick_fix_field();
}
current_sjm= field_sjm;
@ -12266,7 +12348,7 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
Item_equal::get_first() for details.
@return
The transformed condition
The transformed condition, or NULL in case of error
*/
static COND* substitute_for_best_equal_field(JOIN_TAB *context_tab,
@ -18737,8 +18819,6 @@ check_reverse_order:
join_read_first:join_read_last;
tab->type=JT_NEXT; // Read with index_first(), index_next()
if (table->covering_keys.is_set(best_key) && ! table->key_read)
table->enable_keyread();
if (tab->pre_idx_push_select_cond)
{
tab->set_cond(tab->pre_idx_push_select_cond);
@ -18749,6 +18829,7 @@ check_reverse_order:
orig_cond= 0;
orig_cond_saved= false;
}
table->file->ha_index_or_rnd_end();
if (tab->join->select_options & SELECT_DESCRIBE)
{
@ -18756,6 +18837,7 @@ check_reverse_order:
tab->ref.key_parts= 0;
if (select_limit < table->file->stats.records)
tab->limit= select_limit;
table->disable_keyread();
}
}
else if (tab->type != JT_ALL)
@ -20469,6 +20551,8 @@ copy_fields(TMP_TABLE_PARAM *param)
Copy_field *ptr=param->copy_field;
Copy_field *end=param->copy_field_end;
DBUG_ASSERT((ptr != NULL && end >= ptr) || (ptr == NULL && end == NULL));
for (; ptr != end; ptr++)
(*ptr->do_copy)(ptr);
@ -21676,10 +21760,17 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
}
else
{
TABLE_LIST *real_table= table->pos_in_table_list;
item_list.push_back(new Item_string(real_table->alias,
strlen(real_table->alias),
cs));
TABLE_LIST *real_table= table->pos_in_table_list;
/*
Internal temporary tables have no corresponding table reference
object. Such a table may appear in EXPLAIN when a subquery that needs
a temporary table has been executed, and JOIN::exec replaced the
original JOIN with a plan to access the data in the temp table
(made by JOIN::make_simple_join).
*/
const char *tab_name= real_table ? real_table->alias :
"internal_tmp_table";
item_list.push_back(new Item_string(tab_name, strlen(tab_name), cs));
}
/* "partitions" column */
if (explain_flags & DESCRIBE_PARTITIONS)
@ -21844,32 +21935,8 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
}
else
{
ha_rows examined_rows;
if (tab->select && quick)
examined_rows= quick->records;
else if (tab_type == JT_NEXT || tab_type == JT_ALL || is_hj)
{
if (tab->limit)
examined_rows= tab->limit;
else
{
if (tab->table->is_filled_at_execution())
{
examined_rows= tab->records;
}
else
{
/*
handler->info(HA_STATUS_VARIABLE) has been called in
make_join_statistics()
*/
examined_rows= tab->table->file->stats.records;
}
}
}
else
examined_rows=(ha_rows)tab->records_read;
ha_rows examined_rows= tab->get_examined_rows();
item_list.push_back(new Item_int((longlong) (ulonglong) examined_rows,
MY_INT64_NUM_DECIMAL_DIGITS));