diff options
-rw-r--r-- | mysql-test/r/selectivity.result | 40 | ||||
-rw-r--r-- | mysql-test/r/selectivity_innodb.result | 41 | ||||
-rw-r--r-- | mysql-test/t/selectivity.test | 35 | ||||
-rw-r--r-- | sql/opt_range.cc | 19 | ||||
-rw-r--r-- | sql/sql_select.cc | 57 |
5 files changed, 171 insertions, 21 deletions
diff --git a/mysql-test/r/selectivity.result b/mysql-test/r/selectivity.result index b1328fddb3a..28a38c11b01 100644 --- a/mysql-test/r/selectivity.result +++ b/mysql-test/r/selectivity.result @@ -675,4 +675,44 @@ DROP VIEW v1; DROP TABLE t1,t2; set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set use_stat_tables=@tmp_use_stat_tables; +# +# Bug mdev-4349: impossible range for non-indexed column +# +set optimizer_use_condition_selectivity=3; +create table t1 (a int); +insert into t1 values +(3), (7), (2), (5), (7), (1), (2), (2); +set optimizer_use_condition_selectivity=1; +explain extended +select * from t1 where a < 1 and a > 7; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` < 1) and (`test`.`t1`.`a` > 7)) +select * from t1 where a < 1 and a > 7; +a +set optimizer_use_condition_selectivity=3; +explain extended +select * from t1 where a < 1 and a > 7; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0 +select * from t1 where a < 1 and a > 7; +a +drop table t1; +create table t1 (a int); +insert into t1 values (1); +create table t2 (b int); +insert into t2 values (2),(3); +explain extended +select * from t1 where a in ( select b from t2 ) AND ( a > 3 ); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1003 select 1 AS `a` from (`test`.`t2`) where 0 +select * from t1 where a in ( select b from t2 ) AND ( a > 3 ); +a +drop table t1,t2; +set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/r/selectivity_innodb.result b/mysql-test/r/selectivity_innodb.result index 8a620de68e8..02f58dbfebe 100644 --- a/mysql-test/r/selectivity_innodb.result +++ b/mysql-test/r/selectivity_innodb.result @@ -681,6 +681,47 @@ DROP VIEW v1; DROP TABLE t1,t2; set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set use_stat_tables=@tmp_use_stat_tables; +# +# Bug mdev-4349: impossible range for non-indexed column +# +set optimizer_use_condition_selectivity=3; +create table t1 (a int); +insert into t1 values +(3), (7), (2), (5), (7), (1), (2), (2); +set optimizer_use_condition_selectivity=1; +explain extended +select * from t1 where a < 1 and a > 7; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` < 1) and (`test`.`t1`.`a` > 7)) +select * from t1 where a < 1 and a > 7; +a +set optimizer_use_condition_selectivity=3; +explain extended +select * from t1 where a < 1 and a > 7; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0 +select * from t1 where a < 1 and a > 7; +a +drop table t1; +create table t1 (a int); +insert into t1 values (1); +create table t2 (b int); +insert into t2 values (2),(3); +explain extended +select * from t1 where a in ( select b from t2 ) AND ( a > 3 ); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 1 0.00 Using where +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 0 Using where; FirstMatch(t1); Using join buffer (flat, BNL join) +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t2`.`b` = `test`.`t1`.`a`) and (`test`.`t1`.`a` > 3)) +select * from t1 where a in ( select b from t2 ) AND ( a > 3 ); +a +drop table t1,t2; +set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set use_stat_tables=@save_use_stat_tables; set optimizer_switch=@save_optimizer_switch_for_selectivity_test; SET SESSION STORAGE_ENGINE=DEFAULT; diff --git a/mysql-test/t/selectivity.test b/mysql-test/t/selectivity.test index 88bc0683f33..15cb886dc8b 100644 --- a/mysql-test/t/selectivity.test +++ b/mysql-test/t/selectivity.test @@ -267,5 +267,40 @@ DROP TABLE t1,t2; set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set use_stat_tables=@tmp_use_stat_tables; +--echo # +--echo # Bug mdev-4349: impossible range for non-indexed column +--echo # + +set optimizer_use_condition_selectivity=3; + +create table t1 (a int); +insert into t1 values + (3), (7), (2), (5), (7), (1), (2), (2); + +set optimizer_use_condition_selectivity=1; +explain extended +select * from t1 where a < 1 and a > 7; +select * from t1 where a < 1 and a > 7; + +set optimizer_use_condition_selectivity=3; +explain extended +select * from t1 where a < 1 and a > 7; +select * from t1 where a < 1 and a > 7; + +drop table t1; + +create table t1 (a int); +insert into t1 values (1); + +create table t2 (b int); +insert into t2 values (2),(3); + +explain extended +select * from t1 where a in ( select b from t2 ) AND ( a > 3 ); +select * from t1 where a in ( select b from t2 ) AND ( a > 3 ); + +drop table t1,t2; + +set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set use_stat_tables=@save_use_stat_tables; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index fee401d7aac..44c5f619f37 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3325,7 +3325,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond) table->cond_selectivity= 1.0; - if (!bitmap_is_clear_all(used_fields)) + if (thd->variables.optimizer_use_condition_selectivity > 2 && + !bitmap_is_clear_all(used_fields)) { PARAM param; MEM_ROOT alloc; @@ -3362,9 +3363,25 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond) double rows; if (*key) { +#if 0 rows= records_in_column_ranges(¶m, idx, *key); if (rows != HA_POS_ERROR) (*key)->field->cond_selectivity= rows/table_records; +#else + table->reginfo.impossible_range= 0; + if ((*key)->type == SEL_ARG::IMPOSSIBLE) + { + rows= 0; + table->reginfo.impossible_range= 1; + goto free_alloc; + } + else + { + rows= records_in_column_ranges(¶m, idx, *key); + if (rows != HA_POS_ERROR) + (*key)->field->cond_selectivity= rows/table_records; + } +#endif } } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f943b9b20d6..c5671544972 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3794,6 +3794,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, all select distinct fields participate in one index. */ add_group_and_distinct_keys(join, s); + + table->cond_selectivity= 1.0; /* Perform range analysis if there are keys it could use (1). @@ -3802,7 +3804,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, Don't do range analysis for materialized subqueries (4). Don't do range analysis for materialized derived tables (5) */ - if (!s->const_keys.is_clear_all() && // (1) + if ((!s->const_keys.is_clear_all() || + !bitmap_is_clear_all(&s->table->cond_set)) && // (1) (!s->table->pos_in_table_list->embedding || // (2) (s->table->pos_in_table_list->embedding && // (3) s->table->pos_in_table_list->embedding->sj_on_expr)) && // (3) @@ -3810,20 +3813,37 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, !(s->table->pos_in_table_list->derived && // (5) s->table->pos_in_table_list->is_materialized_derived())) // (5) { - ha_rows records; - SQL_SELECT *select; - select= make_select(s->table, found_const_table_map, - found_const_table_map, - *s->on_expr_ref ? *s->on_expr_ref : conds, - 1, &error); - if (!select) - goto error; - records= get_quick_record_count(join->thd, select, s->table, - &s->const_keys, join->row_limit); - s->quick=select->quick; - s->needed_reg=select->needed_reg; - select->quick=0; - if (records == 0 && s->table->reginfo.impossible_range) + bool impossible_range= FALSE; + ha_rows records= HA_POS_ERROR; + SQL_SELECT *select= 0; + if (!s->const_keys.is_clear_all()) + { + select= make_select(s->table, found_const_table_map, + found_const_table_map, + *s->on_expr_ref ? *s->on_expr_ref : conds, + 1, &error); + if (!select) + goto error; + records= get_quick_record_count(join->thd, select, s->table, + &s->const_keys, join->row_limit); + s->quick=select->quick; + s->needed_reg=select->needed_reg; + select->quick=0; + impossible_range= records == 0 && s->table->reginfo.impossible_range; + } + if (!impossible_range) + { + if (join->thd->variables.optimizer_use_condition_selectivity > 1) + calculate_cond_selectivity_for_table(join->thd, s->table, + *s->on_expr_ref ? + *s->on_expr_ref : conds); + if (s->table->reginfo.impossible_range) + { + impossible_range= TRUE; + records= 0; + } + } + if (impossible_range) { /* Impossible WHERE or ON expression @@ -3848,13 +3868,10 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, s->found_records=records; s->read_time= s->quick ? s->quick->read_time : 0.0; } - delete select; + if (select) + delete select; } - if (join->thd->variables.optimizer_use_condition_selectivity > 1) - calculate_cond_selectivity_for_table(join->thd, s->table, - *s->on_expr_ref ? - *s->on_expr_ref : conds); } if (pull_out_semijoin_tables(join)) |