From 1b960d9fd6445998ed31e927ab751afc3d58d99a Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Fri, 10 Oct 2014 23:52:47 +0400 Subject: [PATCH] MDEV-6519: Assertion `join->best_read < double(...)' failed after adding a key to a TokuDB table... - calculate_cond_selectivity_for_table() should handle the case where index statistics is not available (zeros are returned in rec_per_key) --- sql/opt_range.cc | 14 +++++++- .../tokudb_mariadb/r/mdev6519.result | 28 ++++++++++++++++ .../mysql-test/tokudb_mariadb/t/mdev6519.test | 33 +++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 storage/tokudb/mysql-test/tokudb_mariadb/r/mdev6519.result create mode 100644 storage/tokudb/mysql-test/tokudb_mariadb/t/mdev6519.test diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ee26f3745b2..00e81767203 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3547,7 +3547,19 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item *cond) */ double f1= key_info->actual_rec_per_key(i-1); double f2= key_info->actual_rec_per_key(i); - table->cond_selectivity*= f1 / f2; + double selectivity_mult; + if (f1 > 0 && f2 > 0) + selectivity_mult= f1 / f2; + else + { + /* + No statistics available, assume the selectivity is proportional + to the number of key parts. + (i=0 means 1 keypart, i=1 means 2 keyparts, so use i+1) + */ + selectivity_mult= ((double)(i+1)) / i; + } + table->cond_selectivity*= selectivity_mult; } } } diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev6519.result b/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev6519.result new file mode 100644 index 00000000000..b916c133a60 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_mariadb/r/mdev6519.result @@ -0,0 +1,28 @@ +drop table if exists t1; +SET @tmp_ust= @@use_stat_tables; +SET @tmp_oucs= @@optimizer_use_condition_selectivity; +SET use_stat_tables = PREFERABLY; +SET optimizer_use_condition_selectivity = 2; +CREATE TABLE t1 ( +code CHAR(2), +name VARCHAR(32), +population INT, +house_seats TINYINT, +PRIMARY KEY(code), +KEY (house_seats) +) ENGINE=TokuDB; +INSERT INTO t1 VALUES ('AL','Alabama',4833722,7),('AK','Alaska',735132,1); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +ALTER TABLE t1 ADD KEY (name(4),house_seats); +SELECT * FROM t1 WHERE +population BETWEEN 1000000 AND 2000000 +AND name LIKE 'New %' +AND house_seats IN (1, 2, 3) +AND code IN ('NJ', 'NM'); +code name population house_seats +drop table t1; +SET use_stat_tables = @tmp_ust; +SET optimizer_use_condition_selectivity = @tmp_oucs; diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev6519.test b/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev6519.test new file mode 100644 index 00000000000..715aca18025 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_mariadb/t/mdev6519.test @@ -0,0 +1,33 @@ +--disable_warnings +drop table if exists t1; +--enable_warnings + +SET @tmp_ust= @@use_stat_tables; +SET @tmp_oucs= @@optimizer_use_condition_selectivity; + +SET use_stat_tables = PREFERABLY; +SET optimizer_use_condition_selectivity = 2; + +CREATE TABLE t1 ( + code CHAR(2), + name VARCHAR(32), + population INT, + house_seats TINYINT, + PRIMARY KEY(code), + KEY (house_seats) +) ENGINE=TokuDB; + +INSERT INTO t1 VALUES ('AL','Alabama',4833722,7),('AK','Alaska',735132,1); +ANALYZE TABLE t1; +ALTER TABLE t1 ADD KEY (name(4),house_seats); + +SELECT * FROM t1 WHERE +population BETWEEN 1000000 AND 2000000 +AND name LIKE 'New %' +AND house_seats IN (1, 2, 3) +AND code IN ('NJ', 'NM'); + +drop table t1; +SET use_stat_tables = @tmp_ust; +SET optimizer_use_condition_selectivity = @tmp_oucs; +