Commit dff98a8e authored by sergefp@mysql.com's avatar sergefp@mysql.com

* New index_merge EXPLAIN output format

 * Fixed a problem with wrong query results for partially covering keys in ROR-index_merge
 * ROR-intersection retrieval plan choice algorithm now uses less disk IO
   - and properly processes clustered PK range scans 
 * Fixed several minor range optimizer problems
 * Added more comments
 * Code cleanup
parent 8b4ea833
This diff is collapsed.
...@@ -8,7 +8,7 @@ INDEX i2(key2), ...@@ -8,7 +8,7 @@ INDEX i2(key2),
) engine=innodb; ) engine=innodb;
explain select * from t1 where key1 < 5 or key2 > 197; explain select * from t1 where key1 < 5 or key2 > 197;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using where 1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
select * from t1 where key1 < 5 or key2 > 197; select * from t1 where key1 < 5 or key2 > 197;
key1 key2 key1 key2
0 200 0 200
...@@ -18,7 +18,7 @@ key1 key2 ...@@ -18,7 +18,7 @@ key1 key2
4 196 4 196
explain select * from t1 where key1 < 3 or key2 > 195; explain select * from t1 where key1 < 3 or key2 > 195;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using where 1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
select * from t1 where key1 < 3 or key2 > 195; select * from t1 where key1 < 3 or key2 > 195;
key1 key2 key1 key2
0 200 0 200
...@@ -34,7 +34,7 @@ update t1 set str1='aaa', str2='bbb', str3=concat(key2, '-', key1 div 2, '_' ,if ...@@ -34,7 +34,7 @@ update t1 set str1='aaa', str2='bbb', str3=concat(key2, '-', key1 div 2, '_' ,if
alter table t1 add primary key (str1, zeroval, str2, str3); alter table t1 add primary key (str1, zeroval, str2, str3);
explain select * from t1 where key1 < 5 or key2 > 197; explain select * from t1 where key1 < 5 or key2 > 197;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using where 1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
select * from t1 where key1 < 5 or key2 > 197; select * from t1 where key1 < 5 or key2 > 197;
key1 key2 str1 zeroval str2 str3 key1 key2 str1 zeroval str2 str3
4 196 aaa 0 bbb 196-2_a 4 196 aaa 0 bbb 196-2_a
...@@ -44,7 +44,7 @@ key1 key2 str1 zeroval str2 str3 ...@@ -44,7 +44,7 @@ key1 key2 str1 zeroval str2 str3
0 200 aaa 0 bbb 200-0_a 0 200 aaa 0 bbb 200-0_a
explain select * from t1 where key1 < 3 or key2 > 195; explain select * from t1 where key1 < 3 or key2 > 195;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using where 1 SIMPLE t1 index_merge i1,i2 i1,i2 4,4 NULL 8 Using sort_union(i1,i2); Using where
select * from t1 where key1 < 3 or key2 > 195; select * from t1 where key1 < 3 or key2 > 195;
key1 key2 str1 zeroval str2 str3 key1 key2 str1 zeroval str2 str3
4 196 aaa 0 bbb 196-2_a 4 196 aaa 0 bbb 196-2_a
......
This diff is collapsed.
...@@ -41,7 +41,7 @@ pk1 pk2 key1 key2 pktail1ok pktail2ok pktail3bad pktail4bad pktail5bad pk2copy b ...@@ -41,7 +41,7 @@ pk1 pk2 key1 key2 pktail1ok pktail2ok pktail3bad pktail4bad pktail5bad pk2copy b
1 19 0 0 0 0 0 0 0 19 0 filler-data-19 filler2 1 19 0 0 0 0 0 0 0 19 0 filler-data-19 filler2
explain select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1; explain select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 4,4 NULL 1 Using where; Using index 1 SIMPLE t1 index_merge key1,key2 key1,key2 4,4 NULL 1 Using intersect(key1,key2); Using where; Using index
select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1; select pk1,pk2 from t1 where key1 = 10 and key2=10 and 2*pk1+1 < 2*96+1;
pk1 pk2 pk1 pk2
95 50 95 50
...@@ -59,13 +59,19 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -59,13 +59,19 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1 key1 4 const 101 Using where 1 SIMPLE t1 ref key1 key1 4 const 101 Using where
explain select * from t1 where pk1 < 7500 and key1 = 10; explain select * from t1 where pk1 < 7500 and key1 = 10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,key1 key1,PRIMARY 4,4 NULL 38 Using where 1 SIMPLE t1 index_merge PRIMARY,key1 key1,PRIMARY 4,4 NULL 38 Using intersect(key1,PRIMARY); Using where
explain select * from t1 where pktail1ok=1 and key1=10; explain select * from t1 where pktail1ok=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,pktail1ok key1,pktail1ok 4,4 NULL 1 Using where 1 SIMPLE t1 index_merge key1,pktail1ok key1,pktail1ok 4,4 NULL 1 Using intersect(key1,pktail1ok); Using where
explain select * from t1 where pktail2ok=1 and key1=10; explain select * from t1 where pktail2ok=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,pktail2ok key1,pktail2ok 4,4 NULL 1 Using where 1 SIMPLE t1 index_merge key1,pktail2ok key1,pktail2ok 4,4 NULL 1 Using intersect(key1,pktail2ok); Using where
select ' The following is actually a deficiency, it uses sort_union currently:' as 'note:';
note:
The following is actually a deficiency, it uses sort_union currently:
explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,key1,pktail2ok pktail2ok,key1 8,4 NULL 199 Using sort_union(pktail2ok,key1); Using where
explain select * from t1 where pktail3bad=1 and key1=10; explain select * from t1 where pktail3bad=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1,pktail3bad pktail3bad 4 const 98 Using where 1 SIMPLE t1 ref key1,pktail3bad pktail3bad 4 const 98 Using where
...@@ -77,7 +83,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -77,7 +83,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1,pktail5bad pktail5bad 4 const 99 Using where 1 SIMPLE t1 ref key1,pktail5bad pktail5bad 4 const 99 Using where
explain select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10; explain select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge key1,key2 key1,key2 4,4 NULL 1 Using where; Using index 1 SIMPLE t1 index_merge key1,key2 key1,key2 4,4 NULL 1 Using intersect(key1,key2); Using where; Using index
select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10; select pk1,pk2,key1,key2 from t1 where key1 = 10 and key2=10 limit 10;
pk1 pk2 key1 key2 pk1 pk2 key1 key2
95 50 10 10 95 50 10 10
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# ROR-index_merge tests. # ROR-index_merge tests.
# #
--disable_warnings --disable_warnings
drop table if exists t1,t0; drop table if exists t0,t1,t2;
--enable_warnings --enable_warnings
--disable_query_log --disable_query_log
create table t1 create table t1
...@@ -213,3 +213,37 @@ explain select st_a from t1 ...@@ -213,3 +213,37 @@ explain select st_a from t1
drop table t0,t1; drop table t0,t1;
# 'Partially' covered fields test
create table t2 (
a char(10),
b char(10),
filler1 char(255),
filler2 char(255),
key(a(5)),
key(b(5))
);
--disable_query_log
let $1=8;
while ($1)
{
eval insert into t2 values (repeat(char($1+64), 8),repeat(char($1+64), 8),'filler1', 'filler2');
dec $1;
}
insert into t2 select * from t2;
insert into t2 select * from t2;
--enable_query_log
# The table row buffer is reused. Fill it with rows that don't match.
select count(a) from t2 where a='BBBBBBBB';
select count(a) from t2 where b='BBBBBBBB';
# BUG#1:
explain select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
select count(a) from t2 where a='AAAAAAAA' and b='AAAAAAAA';
select count(a) from t2 ignore index(a,b) where a='AAAAAAAA' and b='AAAAAAAA';
insert into t2 values ('ab', 'ab', 'uh', 'oh');
explain select a from t2 where a='ab';
drop table t2;
...@@ -69,6 +69,9 @@ explain select * from t1 where pk1 < 7500 and key1 = 10; ...@@ -69,6 +69,9 @@ explain select * from t1 where pk1 < 7500 and key1 = 10;
explain select * from t1 where pktail1ok=1 and key1=10; explain select * from t1 where pktail1ok=1 and key1=10;
explain select * from t1 where pktail2ok=1 and key1=10; explain select * from t1 where pktail2ok=1 and key1=10;
select ' The following is actually a deficiency, it uses sort_union currently:' as 'note:';
explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10;
explain select * from t1 where pktail3bad=1 and key1=10; explain select * from t1 where pktail3bad=1 and key1=10;
explain select * from t1 where pktail4bad=1 and key1=10; explain select * from t1 where pktail4bad=1 and key1=10;
explain select * from t1 where pktail5bad=1 and key1=10; explain select * from t1 where pktail5bad=1 and key1=10;
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
* when both arguments are bitmaps, they must be of the same size * when both arguments are bitmaps, they must be of the same size
* bitmap_intersect() is an exception :) * bitmap_intersect() is an exception :)
(for for Bitmap::intersect(ulonglong map2buff)) (for for Bitmap::intersect(ulonglong map2buff))
If THREAD is defined all bitmap operations except bitmap_init/bitmap_free
are thread-safe.
TODO: TODO:
Make assembler THREAD safe versions of these using test-and-set instructions Make assembler THREAD safe versions of these using test-and-set instructions
...@@ -332,29 +335,36 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) ...@@ -332,29 +335,36 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
/* /*
Get number of set bits in the bitmap SYNOPSIS
bitmap_bits_set()
map
RETURN
Number of set bits in the bitmap.
*/ */
uint bitmap_bits_set(const MY_BITMAP *map) uint bitmap_bits_set(const MY_BITMAP *map)
{ {
uchar *m= map->bitmap, uchar *m= map->bitmap;
*end= map->bitmap+map->bitmap_size; uchar *end= m + map->bitmap_size;
uint res= 0; uint res= 0;
DBUG_ASSERT(map->bitmap); DBUG_ASSERT(map->bitmap);
bitmap_lock((MY_BITMAP *)map); bitmap_lock((MY_BITMAP *)map);
while (m < end) while (m < end)
{ {
res+= my_count_bits_ushort(*m++); res+= my_count_bits_ushort(*m++);
} }
bitmap_unlock((MY_BITMAP *)map); bitmap_unlock((MY_BITMAP *)map);
return res; return res;
} }
/* /*
Return number of first zero bit or MY_BIT_NONE if all bits are set. SYNOPSIS
bitmap_get_first()
map
RETURN
Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set.
*/ */
uint bitmap_get_first(const MY_BITMAP *map) uint bitmap_get_first(const MY_BITMAP *map)
......
This diff is collapsed.
This diff is collapsed.
...@@ -10077,7 +10077,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -10077,7 +10077,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
select_result *result=join->result; select_result *result=join->result;
Item *item_null= new Item_null(); Item *item_null= new Item_null();
CHARSET_INFO *cs= &my_charset_latin1; CHARSET_INFO *cs= &my_charset_latin1;
int quick_type= -1; int quick_type;
DBUG_ENTER("select_describe"); DBUG_ENTER("select_describe");
DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s", DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
(ulong)join->select_lex, join->select_lex->type, (ulong)join->select_lex, join->select_lex->type,
...@@ -10104,17 +10104,20 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -10104,17 +10104,20 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
{ {
JOIN_TAB *tab=join->join_tab+i; JOIN_TAB *tab=join->join_tab+i;
TABLE *table=tab->table; TABLE *table=tab->table;
char buff[512],*buff_ptr=buff; char buff[512];
char buff1[512], buff2[512], buff3[512]; char buff1[512], buff2[512], buff3[512];
char keylen_str_buf[64]; char keylen_str_buf[64];
char derived_name[64]; char derived_name[64];
String extra(buff, sizeof(buff),cs);
String tmp1(buff1,sizeof(buff1),cs); String tmp1(buff1,sizeof(buff1),cs);
String tmp2(buff2,sizeof(buff2),cs); String tmp2(buff2,sizeof(buff2),cs);
String tmp3(buff3,sizeof(buff3),cs); String tmp3(buff3,sizeof(buff3),cs);
extra.length(0);
tmp1.length(0); tmp1.length(0);
tmp2.length(0); tmp2.length(0);
tmp3.length(0); tmp3.length(0);
quick_type= -1;
item_list.empty(); item_list.empty();
item_list.push_back(new Item_int((int32) item_list.push_back(new Item_int((int32)
join->select_lex->select_number)); join->select_lex->select_number));
...@@ -10165,7 +10168,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -10165,7 +10168,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
else else
item_list.push_back(item_null); item_list.push_back(item_null);
/* Build key,key_len, and ref values and add them to item_list */ /* Build "key", "key_len", and "ref" values and add them to item_list */
if (tab->ref.key_parts) if (tab->ref.key_parts)
{ {
KEY *key_info=table->key_info+ tab->ref.key; KEY *key_info=table->key_info+ tab->ref.key;
...@@ -10200,7 +10203,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -10200,7 +10203,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
} }
else if (tab->select && tab->select->quick) else if (tab->select && tab->select->quick)
{ {
tab->select->quick->fill_keys_and_lengths(&tmp2, &tmp3); 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(tmp2.ptr(),tmp2.length(),cs));
item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs)); item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
item_list.push_back(item_null); item_list.push_back(item_null);
...@@ -10211,9 +10214,11 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -10211,9 +10214,11 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(item_null); item_list.push_back(item_null);
item_list.push_back(item_null); item_list.push_back(item_null);
} }
/* Add "rows" field to item_list. */
item_list.push_back(new Item_int((longlong) (ulonglong) item_list.push_back(new Item_int((longlong) (ulonglong)
join->best_positions[i]. records_read, join->best_positions[i]. records_read,
21)); 21));
/* Build "Extra" field and add it to item_list. */
my_bool key_read=table->key_read; my_bool key_read=table->key_read;
if (tab->type == JT_NEXT && table->used_keys.is_set(tab->index)) if (tab->type == JT_NEXT && table->used_keys.is_set(tab->index))
key_read=1; key_read=1;
...@@ -10225,38 +10230,51 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -10225,38 +10230,51 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs)); item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
else else
{ {
if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
{
extra.append("; Using ");
tab->select->quick->add_info_string(&extra);
}
if (tab->select) if (tab->select)
{ {
if (tab->use_quick == 2) if (tab->use_quick == 2)
{ {
char buf[MAX_KEY/8+1]; char buf[MAX_KEY/8+1];
sprintf(buff_ptr,"; Range checked for each record (index map: 0x%s)", extra.append("; Range checked for each record (index map: 0x");
tab->keys.print(buf)); extra.append(tab->keys.print(buf));
buff_ptr=strend(buff_ptr); extra.append(')');
} }
else else
buff_ptr=strmov(buff_ptr,"; Using where"); extra.append("; Using where");
} }
if (key_read) if (key_read)
buff_ptr= strmov(buff_ptr,"; Using index"); extra.append("; Using index");
if (table->reginfo.not_exists_optimize) if (table->reginfo.not_exists_optimize)
buff_ptr= strmov(buff_ptr,"; Not exists"); extra.append("; Not exists");
if (need_tmp_table) if (need_tmp_table)
{ {
need_tmp_table=0; need_tmp_table=0;
buff_ptr= strmov(buff_ptr,"; Using temporary"); extra.append("; Using temporary");
} }
if (need_order) if (need_order)
{ {
need_order=0; need_order=0;
buff_ptr= strmov(buff_ptr,"; Using filesort"); extra.append("; Using filesort");
} }
if (distinct & test_all_bits(used_tables,thd->used_tables)) if (distinct & test_all_bits(used_tables,thd->used_tables))
buff_ptr= strmov(buff_ptr,"; Distinct"); extra.append("; Distinct");
if (buff_ptr == buff)
buff_ptr+= 2; // Skip inital "; " /* Skip initial "; "*/
item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2, const char *str= extra.ptr();
cs)); uint32 len= extra.length();
if (len)
{
str += 2;
len -= 2;
}
item_list.push_back(new Item_string(str, len, cs));
} }
// For next iteration // For next iteration
used_tables|=table->map; used_tables|=table->map;
......
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