mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Merge 5.3 -> 5.3-subqueries-mwl90
This commit is contained in:
@@ -42,8 +42,8 @@
|
||||
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
|
||||
"MAYBE_REF","ALL","range","index","fulltext",
|
||||
"ref_or_null","unique_subquery","index_subquery",
|
||||
"index_merge","hash"
|
||||
};
|
||||
"index_merge", "hash_ALL", "hash_range",
|
||||
"hash_index", "hash_index_merge" };
|
||||
|
||||
const char *copy_to_tmp_table= "Copying to tmp table";
|
||||
|
||||
@@ -1075,6 +1075,7 @@ JOIN::optimize()
|
||||
for (JOIN_TAB *tab= jt_range->start + first_tab_offs;
|
||||
tab < jt_range->end; tab++)
|
||||
{
|
||||
uint key_copy_index=0;
|
||||
for (uint i=0; i < tab->ref.key_parts; i++)
|
||||
{
|
||||
|
||||
@@ -1090,13 +1091,14 @@ JOIN::optimize()
|
||||
{
|
||||
*ref_item_ptr= ref_item;
|
||||
Item *item= ref_item->real_item();
|
||||
store_key *key_copy= tab->ref.key_copy[i];
|
||||
store_key *key_copy= tab->ref.key_copy[key_copy_index];
|
||||
if (key_copy->type() == store_key::FIELD_STORE_KEY)
|
||||
{
|
||||
store_key_field *field_copy= ((store_key_field *)key_copy);
|
||||
field_copy->change_source_field((Item_field *) item);
|
||||
}
|
||||
}
|
||||
key_copy_index++;
|
||||
}
|
||||
}
|
||||
first_tab_offs= 0;
|
||||
@@ -1735,7 +1737,7 @@ bool JOIN::shrink_join_buffers(JOIN_TAB *jt,
|
||||
cache= tab->cache;
|
||||
if (cache)
|
||||
{
|
||||
ulong buff_size;
|
||||
size_t buff_size;
|
||||
if (needed_space < cache->get_min_join_buffer_size())
|
||||
return TRUE;
|
||||
if (cache->shrink_join_buffer_in_ratio(curr_space, needed_space))
|
||||
@@ -1753,7 +1755,7 @@ bool JOIN::shrink_join_buffers(JOIN_TAB *jt,
|
||||
DBUG_ASSERT(cache);
|
||||
if (needed_space < cache->get_min_join_buffer_size())
|
||||
return TRUE;
|
||||
cache->set_join_buffer_size(needed_space);
|
||||
cache->set_join_buffer_size((size_t)needed_space);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -4085,6 +4087,7 @@ add_keyuse(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field,
|
||||
}
|
||||
keyuse.used_tables= key_field->val->used_tables();
|
||||
keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
|
||||
keyuse.ref_table_rows= 0;
|
||||
keyuse.null_rejecting= key_field->null_rejecting;
|
||||
keyuse.cond_guard= key_field->cond_guard;
|
||||
keyuse.sj_pred_no= key_field->sj_pred_no;
|
||||
@@ -5110,19 +5113,20 @@ best_access_path(JOIN *join,
|
||||
/* Estimate the cost of the hash join access to the table */
|
||||
ha_rows rnd_records= matching_candidates_in_table(s, found_constraint);
|
||||
|
||||
tmp= s->table->file->scan_time();
|
||||
tmp= s->quick ? s->quick->read_time : s->table->file->scan_time();
|
||||
tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
|
||||
|
||||
/* We read the table as many times as join buffer becomes full. */
|
||||
tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
|
||||
record_count /
|
||||
(double) thd->variables.join_buff_size));
|
||||
tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
|
||||
best_time= tmp +
|
||||
(record_count*join_sel) / TIME_FOR_COMPARE * rnd_records;
|
||||
best= tmp;
|
||||
records= rows2double(rnd_records);
|
||||
best_key= hj_start_key;
|
||||
best_ref_depends_map= 0;
|
||||
best_uses_jbuf= test(!disable_jbuf);
|
||||
best_uses_jbuf= TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5596,7 +5600,7 @@ optimize_straight_join(JOIN *join, table_map join_tables)
|
||||
|
||||
All other cases are in-between these two extremes. Thus the parameter
|
||||
'search_depth' controlls the exhaustiveness of the search. The higher the
|
||||
value, the longer the optimizaton time and possibly the better the
|
||||
value, the longer the optimization time and possibly the better the
|
||||
resulting plan. The lower the value, the fewer alternative plans are
|
||||
estimated, but the more likely to get a bad QEP.
|
||||
|
||||
@@ -6698,7 +6702,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
|
||||
keyinfo->key_length=0;
|
||||
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
|
||||
keyinfo->flags= HA_GENERATED_KEY;
|
||||
keyinfo->name= (char *) "hj_key";
|
||||
keyinfo->name= (char *) "$hj";
|
||||
keyinfo->rec_per_key= (ulong*) thd->calloc(sizeof(ulong)*key_parts);
|
||||
if (!keyinfo->rec_per_key)
|
||||
DBUG_RETURN(TRUE);
|
||||
@@ -7400,6 +7404,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
||||
for (tab= next_depth_first_tab(join, NULL); tab;
|
||||
tab= next_depth_first_tab(join, tab), i++)
|
||||
{
|
||||
bool is_hj;
|
||||
/*
|
||||
first_inner is the X in queries like:
|
||||
SELECT * FROM t1 LEFT OUTER JOIN (t2 JOIN t3) ON X
|
||||
@@ -7476,9 +7481,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
||||
add_cond_and_fix(&tmp, tab->select_cond);
|
||||
}
|
||||
|
||||
|
||||
is_hj= (tab->type == JT_REF || tab->type == JT_EQ_REF) &&
|
||||
(join->allowed_join_cache_types & JOIN_CACHE_HASHED_BIT) &&
|
||||
((join->max_allowed_join_cache_level+1)/2 == 2 ||
|
||||
((join->max_allowed_join_cache_level+1)/2 > 2 &&
|
||||
is_hash_join_key_no(tab->ref.key))) &&
|
||||
(!tab->emb_sj_nest ||
|
||||
join->allowed_semijoin_with_cache) &&
|
||||
(!(tab->table->map & join->outer_join) ||
|
||||
join->allowed_outer_join_with_cache);
|
||||
|
||||
if (cond && !tmp && tab->quick)
|
||||
{ // Outer join
|
||||
if (tab->type != JT_ALL)
|
||||
if (tab->type != JT_ALL && !is_hj)
|
||||
{
|
||||
/*
|
||||
Don't use the quick method
|
||||
@@ -7559,9 +7575,10 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
||||
{
|
||||
/* Use quick key read if it's a constant and it's not used
|
||||
with key reading */
|
||||
if (tab->needed_reg.is_clear_all() && tab->type != JT_EQ_REF
|
||||
&& tab->type != JT_FT && (tab->type != JT_REF ||
|
||||
(uint) tab->ref.key == tab->quick->index))
|
||||
if ((tab->needed_reg.is_clear_all() && tab->type != JT_EQ_REF
|
||||
&& tab->type != JT_FT &&
|
||||
(tab->type != JT_REF ||
|
||||
(uint) tab->ref.key == tab->quick->index)) || is_hj)
|
||||
{
|
||||
sel->quick=tab->quick; // Use value from get_quick_...
|
||||
sel->quick_keys.clear_all();
|
||||
@@ -8571,6 +8588,9 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
||||
|
||||
if (jcl)
|
||||
tab[-1].next_select=sub_select_cache;
|
||||
|
||||
if (tab->cache && tab->cache->get_join_alg() == JOIN_CACHE::BNLH_JOIN_ALG)
|
||||
tab->type= JT_HASH;
|
||||
|
||||
switch (tab->type) {
|
||||
case JT_SYSTEM: // Only happens with left join
|
||||
@@ -8584,7 +8604,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
}
|
||||
else if ((!jcl || jcl > 4) && !tab->is_ref_for_hash_join())
|
||||
else if (!jcl || jcl > 4)
|
||||
push_index_cond(tab, tab->ref.key);
|
||||
break;
|
||||
case JT_EQ_REF:
|
||||
@@ -8596,7 +8616,7 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
||||
table->key_read=1;
|
||||
table->file->extra(HA_EXTRA_KEYREAD);
|
||||
}
|
||||
else if ((!jcl || jcl > 4) && !tab->is_ref_for_hash_join())
|
||||
else if (!jcl || jcl > 4)
|
||||
push_index_cond(tab, tab->ref.key);
|
||||
break;
|
||||
case JT_REF_OR_NULL:
|
||||
@@ -8611,10 +8631,11 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
||||
if (table->covering_keys.is_set(tab->ref.key) &&
|
||||
!table->no_keyread)
|
||||
table->enable_keyread();
|
||||
else if ((!jcl || jcl > 4) &&!tab->is_ref_for_hash_join())
|
||||
else if (!jcl || jcl > 4)
|
||||
push_index_cond(tab, tab->ref.key);
|
||||
break;
|
||||
case JT_ALL:
|
||||
case JT_HASH:
|
||||
/*
|
||||
If previous table use cache
|
||||
If the incoming data set is already sorted don't use cache.
|
||||
@@ -8689,7 +8710,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
||||
*/
|
||||
tab->index=find_shortest_key(table, & table->covering_keys);
|
||||
tab->read_first_record= join_read_first;
|
||||
tab->type=JT_NEXT; // Read with index_first / index_next
|
||||
/* Read with index_first / index_next */
|
||||
tab->type= tab->type == JT_ALL ? JT_NEXT : JT_HASH_NEXT;
|
||||
}
|
||||
}
|
||||
if (tab->select && tab->select->quick &&
|
||||
@@ -8734,6 +8756,11 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after)
|
||||
sort_by_tab->type= JT_ALL;
|
||||
sort_by_tab->read_first_record= join_init_read_record;
|
||||
}
|
||||
else if (sort_by_tab->type == JT_HASH_NEXT)
|
||||
{
|
||||
sort_by_tab->type= JT_HASH;
|
||||
sort_by_tab->read_first_record= join_init_read_record;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -13498,6 +13525,11 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table,
|
||||
DBUG_EXECUTE_IF("raise_error", write_err= HA_ERR_FOUND_DUPP_KEY ;);
|
||||
if (write_err)
|
||||
goto err;
|
||||
if (thd->killed)
|
||||
{
|
||||
thd->send_kill_message();
|
||||
goto err_killed;
|
||||
}
|
||||
}
|
||||
if (!new_table.no_rows && new_table.file->ha_end_bulk_insert())
|
||||
goto err;
|
||||
@@ -13530,6 +13562,7 @@ create_internal_tmp_table_from_heap2(THD *thd, TABLE *table,
|
||||
err:
|
||||
DBUG_PRINT("error",("Got error: %d",write_err));
|
||||
table->file->print_error(write_err, MYF(0));
|
||||
err_killed:
|
||||
(void) table->file->ha_rnd_end();
|
||||
(void) new_table.file->close();
|
||||
err1:
|
||||
@@ -19340,7 +19373,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||
TABLE *table=tab->table;
|
||||
TABLE_LIST *table_list= tab->table->pos_in_table_list;
|
||||
char buff[512];
|
||||
char buff1[512], buff2[512], buff3[512];
|
||||
char buff1[512], buff2[512], buff3[512], buff4[512];
|
||||
char keylen_str_buf[64];
|
||||
my_bool key_read;
|
||||
String extra(buff, sizeof(buff),cs);
|
||||
@@ -19348,10 +19381,17 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||
String tmp1(buff1,sizeof(buff1),cs);
|
||||
String tmp2(buff2,sizeof(buff2),cs);
|
||||
String tmp3(buff3,sizeof(buff3),cs);
|
||||
String tmp4(buff4,sizeof(buff4),cs);
|
||||
char hash_key_prefix[]= "#hash#";
|
||||
KEY *key_info= 0;
|
||||
uint key_len= 0;
|
||||
bool is_hj= tab->type == JT_HASH || tab->type ==JT_HASH_NEXT;
|
||||
|
||||
extra.length(0);
|
||||
tmp1.length(0);
|
||||
tmp2.length(0);
|
||||
tmp3.length(0);
|
||||
tmp4.length(0);
|
||||
quick_type= -1;
|
||||
|
||||
/* Don't show eliminated tables */
|
||||
@@ -19369,21 +19409,19 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||
join->select_lex->type;
|
||||
item_list.push_back(new Item_string(stype, strlen(stype), cs));
|
||||
|
||||
if (tab->type == JT_ALL && tab->select && tab->select->quick)
|
||||
if ((tab->type == JT_ALL || tab->type == JT_HASH) &&
|
||||
tab->select && tab->select->quick)
|
||||
{
|
||||
quick_type= tab->select->quick->get_type();
|
||||
if ((quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
|
||||
(quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_INTERSECT) ||
|
||||
(quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
|
||||
(quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION))
|
||||
tab->type = JT_INDEX_MERGE;
|
||||
tab->type= tab->type == JT_ALL ? JT_INDEX_MERGE : JT_HASH_INDEX_MERGE;
|
||||
else
|
||||
tab->type = JT_RANGE;
|
||||
tab->type= tab->type == JT_ALL ? JT_RANGE : JT_HASH_RANGE;
|
||||
}
|
||||
|
||||
if (tab->cache && tab->cache->get_join_alg() == JOIN_CACHE::BNLH_JOIN_ALG)
|
||||
tab->type= JT_HASH;
|
||||
|
||||
/* table */
|
||||
if (table->derived_select_number)
|
||||
{
|
||||
@@ -19455,45 +19493,66 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||
item_list.push_back(item_null);
|
||||
|
||||
/* Build "key", "key_len", and "ref" values and add them to item_list */
|
||||
if (tab->ref.key_parts)
|
||||
if (tab->type == JT_NEXT)
|
||||
{
|
||||
key_info= table->key_info+tab->index;
|
||||
key_len= key_info->key_length;
|
||||
}
|
||||
else if (tab->ref.key_parts)
|
||||
{
|
||||
key_info= tab->get_keyinfo_by_key_no(tab->ref.key);
|
||||
key_len= tab->ref.key_length;
|
||||
}
|
||||
if (key_info)
|
||||
{
|
||||
KEY *key_info= tab->get_keyinfo_by_key_no(tab->ref.key);
|
||||
register uint length;
|
||||
item_list.push_back(new Item_string(key_info->name,
|
||||
strlen(key_info->name),
|
||||
system_charset_info));
|
||||
length= (longlong10_to_str(tab->ref.key_length, keylen_str_buf, 10) -
|
||||
if (is_hj)
|
||||
tmp2.append(hash_key_prefix, strlen(hash_key_prefix), cs);
|
||||
tmp2.append(key_info->name, strlen(key_info->name), cs);
|
||||
length= (longlong10_to_str(key_len, keylen_str_buf, 10) -
|
||||
keylen_str_buf);
|
||||
item_list.push_back(new Item_string(keylen_str_buf, length,
|
||||
system_charset_info));
|
||||
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
|
||||
tmp3.append(keylen_str_buf, length, cs);
|
||||
if (tab->ref.key_parts)
|
||||
{
|
||||
if (tmp2.length())
|
||||
tmp2.append(',');
|
||||
tmp2.append((*ref)->name(), strlen((*ref)->name()),
|
||||
system_charset_info);
|
||||
}
|
||||
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
|
||||
for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
|
||||
{
|
||||
if (tmp4.length())
|
||||
tmp4.append(',');
|
||||
tmp4.append((*ref)->name(), strlen((*ref)->name()), cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tab->type == JT_NEXT)
|
||||
if (is_hj && tab->type != JT_HASH)
|
||||
{
|
||||
tmp2.append(':');
|
||||
tmp3.append(':');
|
||||
}
|
||||
if (tab->type == JT_HASH_NEXT)
|
||||
{
|
||||
KEY *key_info=table->key_info+ tab->index;
|
||||
register uint length;
|
||||
item_list.push_back(new Item_string(key_info->name,
|
||||
strlen(key_info->name),cs));
|
||||
length= (longlong10_to_str(key_info->key_length, keylen_str_buf, 10) -
|
||||
key_info= table->key_info+tab->index;
|
||||
key_len= key_info->key_length;
|
||||
tmp2.append(key_info->name, strlen(key_info->name), cs);
|
||||
length= (longlong10_to_str(key_len, keylen_str_buf, 10) -
|
||||
keylen_str_buf);
|
||||
item_list.push_back(new Item_string(keylen_str_buf,
|
||||
length,
|
||||
system_charset_info));
|
||||
item_list.push_back(item_null);
|
||||
}
|
||||
else if (tab->select && tab->select->quick)
|
||||
{
|
||||
tmp3.append(keylen_str_buf, length, cs);
|
||||
}
|
||||
if (tab->select && tab->select->quick)
|
||||
tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
|
||||
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
|
||||
item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
|
||||
item_list.push_back(item_null);
|
||||
if (key_info || (tab->select && tab->select->quick))
|
||||
{
|
||||
if (tmp2.length())
|
||||
item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
|
||||
else
|
||||
item_list.push_back(item_null);
|
||||
if (tmp3.length())
|
||||
item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
|
||||
else
|
||||
item_list.push_back(item_null);
|
||||
if (key_info && tab->type != JT_NEXT)
|
||||
item_list.push_back(new Item_string(tmp4.ptr(),tmp4.length(),cs));
|
||||
else
|
||||
item_list.push_back(item_null);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -19543,8 +19602,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
||||
ha_rows examined_rows;
|
||||
if (tab->select && tab->select->quick)
|
||||
examined_rows= tab->select->quick->records;
|
||||
else if (tab->type == JT_NEXT || tab->type == JT_ALL ||
|
||||
tab->type == JT_HASH)
|
||||
else if (tab->type == JT_NEXT || tab->type == JT_ALL || is_hj)
|
||||
{
|
||||
if (tab->limit)
|
||||
examined_rows= tab->limit;
|
||||
|
||||
Reference in New Issue
Block a user