Commit 06ef0bda authored by Igor Babaev's avatar Igor Babaev

Fixed bug mdev-5191.

Corrected cost estimates when a join buffer is used and the optimizer is requested
to use condition selectivities.
parent 4bce09c1
This diff is collapsed.
This diff is collapsed.
...@@ -94,7 +94,7 @@ a1 a2 ...@@ -94,7 +94,7 @@ a1 a2
explain extended explain extended
select * from t1i where a1 in (select b1 from t2i where b1 > '0'); select * from t1i where a1 in (select b1 from t2i where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2i index it2i1,it2i3 it2i1 # NULL 5 40.00 Using where; Using index; LooseScan 1 PRIMARY t2i index it2i1,it2i3 it2i1 # NULL 5 50.00 Using where; Using index; LooseScan
1 PRIMARY t1i ref _it1_idx _it1_idx # _ref_ 1 100.00 1 PRIMARY t1i ref _it1_idx _it1_idx # _ref_ 1 100.00
Warnings: Warnings:
Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) where ((`test`.`t1i`.`a1` = `test`.`t2i`.`b1`) and (`test`.`t2i`.`b1` > '0')) Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) where ((`test`.`t1i`.`a1` = `test`.`t2i`.`b1`) and (`test`.`t2i`.`b1` > '0'))
...@@ -117,7 +117,7 @@ a1 a2 ...@@ -117,7 +117,7 @@ a1 a2
explain extended explain extended
select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0'); select * from t1i where (a1, a2) in (select b1, b2 from t2i where b1 > '0');
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2i index it2i1,it2i2,it2i3 it2i3 # NULL 5 40.00 Using where; Using index; LooseScan 1 PRIMARY t2i index it2i1,it2i2,it2i3 it2i3 # NULL 5 50.00 Using where; Using index; LooseScan
1 PRIMARY t1i ref _it1_idx _it1_idx # _ref_ 1 100.00 1 PRIMARY t1i ref _it1_idx _it1_idx # _ref_ 1 100.00
Warnings: Warnings:
Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) where ((`test`.`t1i`.`a1` = `test`.`t2i`.`b1`) and (`test`.`t1i`.`a2` = `test`.`t2i`.`b2`) and (`test`.`t2i`.`b1` > '0')) Note 1003 select `test`.`t1i`.`a1` AS `a1`,`test`.`t1i`.`a2` AS `a2` from `test`.`t1i` semi join (`test`.`t2i`) where ((`test`.`t1i`.`a1` = `test`.`t2i`.`b1`) and (`test`.`t1i`.`a2` = `test`.`t2i`.`b2`) and (`test`.`t2i`.`b1` > '0'))
...@@ -319,7 +319,7 @@ where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and ...@@ -319,7 +319,7 @@ where (a1, a2) in (select b1, b2 from t2i where b1 > '0') and
(a1, a2) in (select c1, c2 from t3i (a1, a2) in (select c1, c2 from t3i
where (c1, c2) in (select b1, b2 from t2i where b2 > '0')); where (c1, c2) in (select b1, b2 from t2i where b2 > '0'));
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t2i index it2i1,it2i2,it2i3 # # # 5 40.00 # 1 PRIMARY t2i index it2i1,it2i2,it2i3 # # # 5 50.00 #
1 PRIMARY t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 # 1 PRIMARY t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
1 PRIMARY t3i ref it3i1,it3i2,it3i3 # # # 1 100.00 # 1 PRIMARY t3i ref it3i1,it3i2,it3i3 # # # 1 100.00 #
1 PRIMARY t2i ref it2i1,it2i2,it2i3 # # # 2 100.00 # 1 PRIMARY t2i ref it2i1,it2i2,it2i3 # # # 2 100.00 #
...@@ -407,7 +407,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -407,7 +407,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 MATERIALIZED t2 ALL NULL # # # 5 100.00 # 2 MATERIALIZED t2 ALL NULL # # # 5 100.00 #
4 MATERIALIZED t3 ALL NULL # # # 4 100.00 # 4 MATERIALIZED t3 ALL NULL # # # 4 100.00 #
3 MATERIALIZED t3 ALL NULL # # # 4 100.00 # 3 MATERIALIZED t3 ALL NULL # # # 4 100.00 #
7 UNION t2i index it2i1,it2i2,it2i3 # # # 5 40.00 # 7 UNION t2i index it2i1,it2i2,it2i3 # # # 5 50.00 #
7 UNION t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 # 7 UNION t1i ref it1i1,it1i2,it1i3 # # # 1 100.00 #
7 UNION t3i ref it3i1,it3i2,it3i3 # # # 1 100.00 # 7 UNION t3i ref it3i1,it3i2,it3i3 # # # 1 100.00 #
7 UNION t2i ref it2i1,it2i2,it2i3 # # # 2 100.00 # 7 UNION t2i ref it2i1,it2i2,it2i3 # # # 2 100.00 #
......
...@@ -739,3 +739,58 @@ DROP TABLE t1,t2,t3; ...@@ -739,3 +739,58 @@ DROP TABLE t1,t2,t3;
set use_stat_tables=@save_use_stat_tables; set use_stat_tables=@save_use_stat_tables;
--echo #
--echo # Bug mdev-5191: performance degradation due to a suboptimal chosen plan
--echo # when optimizer_use_condition_selectivity=3
--echo #
set use_stat_tables = 'preferably';
set @@RAND_SEED1=810763568, @@RAND_SEED2=600681772;
set TIMESTAMP=1394806993;
create table t1 (a int, b int) engine=myisam;
insert t1 values (rand()*1e5, rand()*1e5);
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
insert t1 select rand()*1e5, rand()*1e5 from t1;
create table t2 (c int, d int, key(c), key(d)) engine=myisam;
insert t2 select floor(rand()*1e5/2)*2, floor(rand()*1e5/3)*3 from t1;
analyze table t1,t2;
set optimizer_use_condition_selectivity=1;
explain extended
select * from t1, t2, t1 as t3
where t1.b=t2.c and t2.d=t3.a and t3.b<5 and t1.a < 2000;
select * from t1, t2, t1 as t3
where t1.b=t2.c and t2.d=t3.a and t3.b<5 and t1.a < 2000;
set optimizer_use_condition_selectivity=3;
explain extended
select * from t1, t2, t1 as t3
where t1.b=t2.c and t2.d=t3.a and t3.b<5 and t1.a < 2000;
select * from t1, t2, t1 as t3
where t1.b=t2.c and t2.d=t3.a and t3.b<5 and t1.a < 2000;
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
drop table t1,t2;
set use_stat_tables=@save_use_stat_tables;
...@@ -5565,9 +5565,23 @@ void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key) ...@@ -5565,9 +5565,23 @@ void set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
/* Estimate of the number matching candidates in the joined table */ /* Estimate of the number matching candidates in the joined table */
inline inline
ha_rows matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint) double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint,
uint use_cond_selectivity)
{ {
ha_rows records= s->found_records; ha_rows records;
double dbl_records;
if (use_cond_selectivity > 1)
{
TABLE *table= s->table;
double sel= table->cond_selectivity;
double table_records= table->stat_records();
dbl_records= table_records * sel;
return dbl_records;
}
records = s->found_records;
/* /*
If there is a filtering condition on the table (i.e. ref analyzer found If there is a filtering condition on the table (i.e. ref analyzer found
at least one "table.keyXpartY= exprZ", where exprZ refers only to tables at least one "table.keyXpartY= exprZ", where exprZ refers only to tables
...@@ -5587,7 +5601,8 @@ ha_rows matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint) ...@@ -5587,7 +5601,8 @@ ha_rows matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint)
if (s->table->quick_condition_rows != s->found_records) if (s->table->quick_condition_rows != s->found_records)
records= s->table->quick_condition_rows; records= s->table->quick_condition_rows;
return records; dbl_records= records;
return dbl_records;
} }
...@@ -5630,6 +5645,7 @@ best_access_path(JOIN *join, ...@@ -5630,6 +5645,7 @@ best_access_path(JOIN *join,
POSITION *loose_scan_pos) POSITION *loose_scan_pos)
{ {
THD *thd= join->thd; THD *thd= join->thd;
uint use_cond_selectivity= thd->variables.optimizer_use_condition_selectivity;
KEYUSE *best_key= 0; KEYUSE *best_key= 0;
uint best_max_key_part= 0; uint best_max_key_part= 0;
my_bool found_constraint= 0; my_bool found_constraint= 0;
...@@ -6061,7 +6077,8 @@ best_access_path(JOIN *join, ...@@ -6061,7 +6077,8 @@ best_access_path(JOIN *join,
{ {
double join_sel= 0.1; double join_sel= 0.1;
/* Estimate the cost of the hash join access to the table */ /* Estimate the cost of the hash join access to the table */
ha_rows rnd_records= matching_candidates_in_table(s, found_constraint); double rnd_records= matching_candidates_in_table(s, found_constraint,
use_cond_selectivity);
tmp= s->quick ? s->quick->read_time : s->scan_time(); tmp= s->quick ? s->quick->read_time : s->scan_time();
tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE; tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
...@@ -6073,7 +6090,7 @@ best_access_path(JOIN *join, ...@@ -6073,7 +6090,7 @@ best_access_path(JOIN *join,
best_time= tmp + best_time= tmp +
(record_count*join_sel) / TIME_FOR_COMPARE * rnd_records; (record_count*join_sel) / TIME_FOR_COMPARE * rnd_records;
best= tmp; best= tmp;
records= rows2double(rnd_records); records= rnd_records;
best_key= hj_start_key; best_key= hj_start_key;
best_ref_depends_map= 0; best_ref_depends_map= 0;
best_uses_jbuf= TRUE; best_uses_jbuf= TRUE;
...@@ -6120,7 +6137,8 @@ best_access_path(JOIN *join, ...@@ -6120,7 +6137,8 @@ best_access_path(JOIN *join,
!(s->table->force_index && best_key && !s->quick) && // (4) !(s->table->force_index && best_key && !s->quick) && // (4)
!(best_key && s->table->pos_in_table_list->jtbm_subselect)) // (5) !(best_key && s->table->pos_in_table_list->jtbm_subselect)) // (5)
{ // Check full join { // Check full join
ha_rows rnd_records= matching_candidates_in_table(s, found_constraint); double rnd_records= matching_candidates_in_table(s, found_constraint,
use_cond_selectivity);
/* /*
Range optimizer never proposes a RANGE if it isn't better Range optimizer never proposes a RANGE if it isn't better
...@@ -6193,7 +6211,7 @@ best_access_path(JOIN *join, ...@@ -6193,7 +6211,7 @@ best_access_path(JOIN *join,
will ensure that this will be used will ensure that this will be used
*/ */
best= tmp; best= tmp;
records= rows2double(rnd_records); records= rnd_records;
best_key= 0; best_key= 0;
/* range/index_merge/ALL/index access method are "independent", so: */ /* range/index_merge/ALL/index access method are "independent", so: */
best_ref_depends_map= 0; best_ref_depends_map= 0;
...@@ -7298,6 +7316,10 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, ...@@ -7298,6 +7316,10 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
keyuse++; keyuse++;
} while (keyuse->table == table && keyuse->key == key); } while (keyuse->table == table && keyuse->key == key);
} }
else
{
sel= 1;
}
/* /*
If the field f from the table is equal to a field from one the If the field f from the table is equal to a field from one the
...@@ -8312,7 +8334,7 @@ get_best_combination(JOIN *join) ...@@ -8312,7 +8334,7 @@ get_best_combination(JOIN *join)
Save records_read in JOIN_TAB so that select_describe()/etc don't have Save records_read in JOIN_TAB so that select_describe()/etc don't have
to access join->best_positions[]. to access join->best_positions[].
*/ */
j->records_read= (ha_rows)join->best_positions[tablenr].records_read; j->records_read= join->best_positions[tablenr].records_read;
j->cond_selectivity= join->best_positions[tablenr].cond_selectivity; j->cond_selectivity= join->best_positions[tablenr].cond_selectivity;
join->map2table[j->table->tablenr]= j; join->map2table[j->table->tablenr]= j;
......
...@@ -296,8 +296,7 @@ typedef struct st_join_table { ...@@ -296,8 +296,7 @@ typedef struct st_join_table {
*/ */
double read_time; double read_time;
/* psergey-todo: make the below have type double, like POSITION::records_read? */ double records_read;
ha_rows records_read;
/* The selectivity of the conditions that can be pushed to the table */ /* The selectivity of the conditions that can be pushed to the table */
double cond_selectivity; double cond_selectivity;
......
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