Skip to content

Commit 9d4a0dd

Browse files
committed
Fixed bug mdev-11096.
1. When min/max value is provided the null flag for it must be set to 0 in the bitmap Culumn_statistics::column_stat_nulls. 2. When the calculation of the selectivity of the range condition over a column requires min and max values for the column then we have to check that these values are provided.
1 parent 26b87c3 commit 9d4a0dd

File tree

5 files changed

+78
-13
lines changed

5 files changed

+78
-13
lines changed

mysql-test/r/selectivity.result

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,3 +1446,27 @@ a b i
14461446
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
14471447
DROP TABLE t1,t2;
14481448
set use_stat_tables=@save_use_stat_tables;
1449+
#
1450+
# Bug mdev-11096: range condition over column without statistical data
1451+
#
1452+
set use_stat_tables='preferably';
1453+
set optimizer_use_condition_selectivity=3;
1454+
create table t1(col1 char(32));
1455+
insert into t1 values ('a'),('b'),('c'),('d'), ('e'),('f'),('g'),('h');
1456+
analyze table t1 persistent for columns () indexes ();
1457+
Table Op Msg_type Msg_text
1458+
test.t1 analyze status Engine-independent statistics collected
1459+
test.t1 analyze status OK
1460+
explain extended
1461+
select * from t1 where col1 > 'b' and col1 < 'e';
1462+
id select_type table type possible_keys key key_len ref rows filtered Extra
1463+
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
1464+
Warnings:
1465+
Note 1003 select `test`.`t1`.`col1` AS `col1` from `test`.`t1` where ((`test`.`t1`.`col1` > 'b') and (`test`.`t1`.`col1` < 'e'))
1466+
select * from t1 where col1 > 'b' and col1 < 'e';
1467+
col1
1468+
c
1469+
d
1470+
drop table t1;
1471+
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
1472+
set use_stat_tables=@save_use_stat_tables;

mysql-test/r/selectivity_innodb.result

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -802,9 +802,9 @@ insert into t2 values (2),(3);
802802
explain extended
803803
select * from t1 where a in ( select b from t2 ) AND ( a > 3 );
804804
id select_type table type possible_keys key key_len ref rows filtered Extra
805-
1 PRIMARY t1 ALL NULL NULL NULL NULL 1 0.00 Using where
805+
1 PRIMARY t1 ALL NULL NULL NULL NULL 1 100.00 Using where
806806
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
807-
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 0.00
807+
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00
808808
Warnings:
809809
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` semi join (`test`.`t2`) where ((`test`.`t1`.`a` > 3))
810810
select * from t1 where a in ( select b from t2 ) AND ( a > 3 );
@@ -1450,6 +1450,30 @@ a b i
14501450
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
14511451
DROP TABLE t1,t2;
14521452
set use_stat_tables=@save_use_stat_tables;
1453+
#
1454+
# Bug mdev-11096: range condition over column without statistical data
1455+
#
1456+
set use_stat_tables='preferably';
1457+
set optimizer_use_condition_selectivity=3;
1458+
create table t1(col1 char(32));
1459+
insert into t1 values ('a'),('b'),('c'),('d'), ('e'),('f'),('g'),('h');
1460+
analyze table t1 persistent for columns () indexes ();
1461+
Table Op Msg_type Msg_text
1462+
test.t1 analyze status Engine-independent statistics collected
1463+
test.t1 analyze status OK
1464+
explain extended
1465+
select * from t1 where col1 > 'b' and col1 < 'e';
1466+
id select_type table type possible_keys key key_len ref rows filtered Extra
1467+
1 SIMPLE t1 ALL NULL NULL NULL NULL 8 100.00 Using where
1468+
Warnings:
1469+
Note 1003 select `test`.`t1`.`col1` AS `col1` from `test`.`t1` where ((`test`.`t1`.`col1` > 'b') and (`test`.`t1`.`col1` < 'e'))
1470+
select * from t1 where col1 > 'b' and col1 < 'e';
1471+
col1
1472+
c
1473+
d
1474+
drop table t1;
1475+
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
1476+
set use_stat_tables=@save_use_stat_tables;
14531477
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
14541478
set @tmp_ust= @@use_stat_tables;
14551479
set @tmp_oucs= @@optimizer_use_condition_selectivity;

mysql-test/t/selectivity.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,25 @@ set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivit
970970

971971
DROP TABLE t1,t2;
972972

973+
set use_stat_tables=@save_use_stat_tables;
974+
975+
--echo #
976+
--echo # Bug mdev-11096: range condition over column without statistical data
977+
--echo #
978+
979+
set use_stat_tables='preferably';
980+
set optimizer_use_condition_selectivity=3;
973981

982+
create table t1(col1 char(32));
983+
insert into t1 values ('a'),('b'),('c'),('d'), ('e'),('f'),('g'),('h');
984+
analyze table t1 persistent for columns () indexes ();
985+
986+
explain extended
987+
select * from t1 where col1 > 'b' and col1 < 'e';
988+
select * from t1 where col1 > 'b' and col1 < 'e';
989+
990+
drop table t1;
991+
992+
set optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
974993
set use_stat_tables=@save_use_stat_tables;
975994

sql/sql_statistics.cc

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,11 +1003,13 @@ class Column_stat: public Stat_table
10031003

10041004
switch (i) {
10051005
case COLUMN_STAT_MIN_VALUE:
1006+
table_field->read_stats->min_value->set_notnull();
10061007
stat_field->val_str(&val);
10071008
table_field->read_stats->min_value->store(val.ptr(), val.length(),
10081009
&my_charset_bin);
10091010
break;
10101011
case COLUMN_STAT_MAX_VALUE:
1012+
table_field->read_stats->max_value->set_notnull();
10111013
stat_field->val_str(&val);
10121014
table_field->read_stats->max_value->store(val.ptr(), val.length(),
10131015
&my_charset_bin);
@@ -3659,17 +3661,8 @@ double get_column_range_cardinality(Field *field,
36593661
{
36603662
double avg_frequency= col_stats->get_avg_frequency();
36613663
res= avg_frequency;
3662-
/*
3663-
psergey-todo: what does check for min_value, max_value mean?
3664-
min/max_value are set to NULL in alloc_statistics_for_table() and
3665-
alloc_statistics_for_table_share(). Both functions will immediately
3666-
call create_min_max_statistical_fields_for_table and
3667-
create_min_max_statistical_fields_for_table_share() respectively,
3668-
which will set min/max_value to be valid pointers, unless OOM
3669-
occurs.
3670-
*/
36713664
if (avg_frequency > 1.0 + 0.000001 &&
3672-
col_stats->min_value && col_stats->max_value)
3665+
col_stats->min_max_values_are_provided())
36733666
{
36743667
Histogram *hist= &col_stats->histogram;
36753668
if (hist->is_available())
@@ -3692,7 +3685,7 @@ double get_column_range_cardinality(Field *field,
36923685
}
36933686
else
36943687
{
3695-
if (col_stats->min_value && col_stats->max_value)
3688+
if (col_stats->min_max_values_are_provided())
36963689
{
36973690
double sel, min_mp_pos, max_mp_pos;
36983691

sql/sql_statistics.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,11 @@ class Column_statistics
388388
avg_frequency= (ulong) (val * Scale_factor_avg_frequency);
389389
}
390390

391+
bool min_max_values_are_provided()
392+
{
393+
return !is_null(COLUMN_STAT_MIN_VALUE) &&
394+
!is_null(COLUMN_STAT_MIN_VALUE);
395+
}
391396
};
392397

393398

0 commit comments

Comments
 (0)