mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Merged Performance Version 0.2.1 with latest 5.1 tree (last push 11 feb 14.01.13 2009)
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2000-2006 MySQL AB
|
||||
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
|
||||
|
||||
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
|
||||
@ -88,7 +88,6 @@ static store_key *get_store_key(THD *thd,
|
||||
KEYUSE *keyuse, table_map used_tables,
|
||||
KEY_PART_INFO *key_part, uchar *key_buff,
|
||||
uint maybe_null);
|
||||
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
|
||||
static void make_outerjoin_info(JOIN *join);
|
||||
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
|
||||
static void make_join_readinfo(JOIN *join, ulonglong options);
|
||||
@ -110,7 +109,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
|
||||
void *table_join_idx);
|
||||
static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
|
||||
COND *conds, bool top);
|
||||
static bool check_interleaving_with_nj(JOIN_TAB *last, JOIN_TAB *next);
|
||||
static bool check_interleaving_with_nj(JOIN_TAB *next);
|
||||
static void restore_prev_nj_state(JOIN_TAB *last);
|
||||
static void reset_nj_counters(List<TABLE_LIST> *join_list);
|
||||
static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list,
|
||||
@ -1670,14 +1669,22 @@ JOIN::exec()
|
||||
(zero_result_cause?zero_result_cause:"No tables used"));
|
||||
else
|
||||
{
|
||||
result->send_fields(*columns_list,
|
||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
||||
if (result->send_fields(*columns_list,
|
||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||
{
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
/*
|
||||
We have to test for 'conds' here as the WHERE may not be constant
|
||||
even if we don't have any tables for prepared statements or if
|
||||
conds uses something like 'rand()'.
|
||||
If the HAVING clause is either impossible or always true, then
|
||||
JOIN::having is set to NULL by optimize_cond.
|
||||
In this case JOIN::exec must check for JOIN::having_value, in the
|
||||
same way it checks for JOIN::cond_value.
|
||||
*/
|
||||
if (cond_value != Item::COND_FALSE &&
|
||||
having_value != Item::COND_FALSE &&
|
||||
(!conds || conds->val_int()) &&
|
||||
(!having || having->val_int()))
|
||||
{
|
||||
@ -1874,7 +1881,7 @@ JOIN::exec()
|
||||
|
||||
/* Free first data from old join */
|
||||
curr_join->join_free();
|
||||
if (make_simple_join(curr_join, curr_tmp_table))
|
||||
if (curr_join->make_simple_join(this, curr_tmp_table))
|
||||
DBUG_VOID_RETURN;
|
||||
calc_group_buffer(curr_join, group_list);
|
||||
count_field_types(select_lex, &curr_join->tmp_table_param,
|
||||
@ -1997,7 +2004,7 @@ JOIN::exec()
|
||||
curr_join->select_distinct=0;
|
||||
}
|
||||
curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
|
||||
if (make_simple_join(curr_join, curr_tmp_table))
|
||||
if (curr_join->make_simple_join(this, curr_tmp_table))
|
||||
DBUG_VOID_RETURN;
|
||||
calc_group_buffer(curr_join, curr_join->group_list);
|
||||
count_field_types(select_lex, &curr_join->tmp_table_param,
|
||||
@ -2587,7 +2594,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
||||
if (s->dependent & table->map)
|
||||
s->dependent |= table->reginfo.join_tab->dependent;
|
||||
}
|
||||
if (s->dependent)
|
||||
if (outer_join & s->table->map)
|
||||
s->table->maybe_null= 1;
|
||||
}
|
||||
/* Catch illegal cross references for outer joins */
|
||||
@ -4889,6 +4896,18 @@ greedy_search(JOIN *join,
|
||||
*/
|
||||
join->positions[idx]= best_pos;
|
||||
|
||||
/*
|
||||
Update the interleaving state after extending the current partial plan
|
||||
with a new table.
|
||||
We are doing this here because best_extension_by_limited_search reverts
|
||||
the interleaving state to the one of the non-extended partial plan
|
||||
on exit.
|
||||
*/
|
||||
IF_DBUG(bool is_interleave_error= )
|
||||
check_interleaving_with_nj (best_table);
|
||||
/* This has been already checked by best_extension_by_limited_search */
|
||||
DBUG_ASSERT(!is_interleave_error);
|
||||
|
||||
/* find the position of 'best_table' in 'join->best_ref' */
|
||||
best_idx= idx;
|
||||
JOIN_TAB *pos= join->best_ref[best_idx];
|
||||
@ -4906,7 +4925,7 @@ greedy_search(JOIN *join,
|
||||
--size_remain;
|
||||
++idx;
|
||||
|
||||
DBUG_EXECUTE("opt", print_plan(join, join->tables,
|
||||
DBUG_EXECUTE("opt", print_plan(join, idx,
|
||||
record_count, read_time, read_time,
|
||||
"extended"););
|
||||
} while (TRUE);
|
||||
@ -5064,7 +5083,7 @@ best_extension_by_limited_search(JOIN *join,
|
||||
table_map real_table_bit= s->table->map;
|
||||
if ((remaining_tables & real_table_bit) &&
|
||||
!(remaining_tables & s->dependent) &&
|
||||
(!idx || !check_interleaving_with_nj(join->positions[idx-1].table, s)))
|
||||
(!idx || !check_interleaving_with_nj(s)))
|
||||
{
|
||||
double current_record_count, current_read_time;
|
||||
|
||||
@ -5210,7 +5229,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
|
||||
{
|
||||
table_map real_table_bit=s->table->map;
|
||||
if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) &&
|
||||
(!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s)))
|
||||
(!idx|| !check_interleaving_with_nj(s)))
|
||||
{
|
||||
double records, best;
|
||||
best_access_path(join, s, thd, rest_tables, idx, record_count,
|
||||
@ -5669,48 +5688,42 @@ store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
make_simple_join(JOIN *join,TABLE *tmp_table)
|
||||
/**
|
||||
@details Initialize a JOIN as a query execution plan
|
||||
that accesses a single table via a table scan.
|
||||
|
||||
@param parent contains JOIN_TAB and TABLE object buffers for this join
|
||||
@param tmp_table temporary table
|
||||
|
||||
@retval FALSE success
|
||||
@retval TRUE error occurred
|
||||
*/
|
||||
bool
|
||||
JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
|
||||
{
|
||||
TABLE **tableptr;
|
||||
JOIN_TAB *join_tab;
|
||||
DBUG_ENTER("make_simple_join");
|
||||
DBUG_ENTER("JOIN::make_simple_join");
|
||||
|
||||
/*
|
||||
Reuse TABLE * and JOIN_TAB if already allocated by a previous call
|
||||
to this function through JOIN::exec (may happen for sub-queries).
|
||||
*/
|
||||
if (!join->table_reexec)
|
||||
{
|
||||
if (!(join->table_reexec= (TABLE**) join->thd->alloc(sizeof(TABLE*))))
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
if (join->tmp_join)
|
||||
join->tmp_join->table_reexec= join->table_reexec;
|
||||
}
|
||||
if (!join->join_tab_reexec)
|
||||
{
|
||||
if (!(join->join_tab_reexec=
|
||||
(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
if (join->tmp_join)
|
||||
join->tmp_join->join_tab_reexec= join->join_tab_reexec;
|
||||
}
|
||||
tableptr= join->table_reexec;
|
||||
join_tab= join->join_tab_reexec;
|
||||
if (!parent->join_tab_reexec &&
|
||||
!(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB))))
|
||||
DBUG_RETURN(TRUE); /* purecov: inspected */
|
||||
|
||||
join->join_tab=join_tab;
|
||||
join->table=tableptr; tableptr[0]=tmp_table;
|
||||
join->tables=1;
|
||||
join->const_tables=0;
|
||||
join->const_table_map=0;
|
||||
join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count=
|
||||
join->tmp_table_param.func_count=0;
|
||||
join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0;
|
||||
join->first_record=join->sort_and_group=0;
|
||||
join->send_records=(ha_rows) 0;
|
||||
join->group=0;
|
||||
join->row_limit=join->unit->select_limit_cnt;
|
||||
join->do_send_rows = (join->row_limit) ? 1 : 0;
|
||||
join_tab= parent->join_tab_reexec;
|
||||
table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table;
|
||||
tables= 1;
|
||||
const_tables= 0;
|
||||
const_table_map= 0;
|
||||
tmp_table_param.field_count= tmp_table_param.sum_func_count=
|
||||
tmp_table_param.func_count= 0;
|
||||
tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
|
||||
first_record= sort_and_group=0;
|
||||
send_records= (ha_rows) 0;
|
||||
group= 0;
|
||||
row_limit= unit->select_limit_cnt;
|
||||
do_send_rows= row_limit ? 1 : 0;
|
||||
|
||||
join_tab->cache.buff=0; /* No caching */
|
||||
join_tab->table=tmp_table;
|
||||
@ -5727,7 +5740,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
|
||||
join_tab->ref.key = -1;
|
||||
join_tab->not_used_in_distinct=0;
|
||||
join_tab->read_first_record= join_init_read_record;
|
||||
join_tab->join=join;
|
||||
join_tab->join= this;
|
||||
join_tab->ref.key_parts= 0;
|
||||
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
|
||||
tmp_table->status=0;
|
||||
@ -8790,9 +8803,6 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list)
|
||||
the partial join order.
|
||||
@endverbatim
|
||||
|
||||
@param join Join being processed
|
||||
@param last_tab Last table in current partial join order (this function is
|
||||
not called for empty partial join orders)
|
||||
@param next_tab Table we're going to extend the current partial join with
|
||||
|
||||
@retval
|
||||
@ -8802,10 +8812,10 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list)
|
||||
TRUE Requested join order extension not allowed.
|
||||
*/
|
||||
|
||||
static bool check_interleaving_with_nj(JOIN_TAB *last_tab, JOIN_TAB *next_tab)
|
||||
static bool check_interleaving_with_nj(JOIN_TAB *next_tab)
|
||||
{
|
||||
TABLE_LIST *next_emb= next_tab->table->pos_in_table_list->embedding;
|
||||
JOIN *join= last_tab->join;
|
||||
JOIN *join= next_tab->join;
|
||||
|
||||
if (join->cur_embedding_map & ~next_tab->embedding_map)
|
||||
{
|
||||
@ -13866,6 +13876,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
|
||||
length=0;
|
||||
for (i=0 ; i < table_count ; i++)
|
||||
{
|
||||
bool have_bit_fields= FALSE;
|
||||
uint null_fields=0,used_fields;
|
||||
Field **f_ptr,*field;
|
||||
MY_BITMAP *read_set= tables[i].table->read_set;
|
||||
@ -13880,13 +13891,16 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
|
||||
length+=field->fill_cache_field(copy);
|
||||
if (copy->blob_field)
|
||||
(*blob_ptr++)=copy;
|
||||
if (field->maybe_null())
|
||||
if (field->real_maybe_null())
|
||||
null_fields++;
|
||||
if (field->type() == MYSQL_TYPE_BIT &&
|
||||
((Field_bit*)field)->bit_len)
|
||||
have_bit_fields= TRUE;
|
||||
copy++;
|
||||
}
|
||||
}
|
||||
/* Copy null bits from table */
|
||||
if (null_fields && tables[i].table->s->null_fields)
|
||||
if (null_fields || have_bit_fields)
|
||||
{ /* must copy null bits */
|
||||
copy->str= tables[i].table->null_flags;
|
||||
copy->length= tables[i].table->s->null_bytes;
|
||||
|
Reference in New Issue
Block a user