diff options
author | Guilhem Bichot <guilhem@mysql.com> | 2009-10-05 22:59:19 +0200 |
---|---|---|
committer | Guilhem Bichot <guilhem@mysql.com> | 2009-10-05 22:59:19 +0200 |
commit | 56312dc7cf7cc3be5e510b3ef743cb29d8783b7e (patch) | |
tree | 6cab0463ca3fd874c305f3ee285b970919ac1304 | |
parent | 42e807783465ea9b3bc60746baafbb07c1462b68 (diff) | |
download | mariadb-git-56312dc7cf7cc3be5e510b3ef743cb29d8783b7e.tar.gz |
Backport of the fix for BUG#33730 "Full table scan instead selected partitions for query more than 10 partitions"
from 6.0, made in sergefp@mysql.com-20090205190644-q8632sniogedhtsu
-rw-r--r-- | mysql-test/r/partition_hash.result | 2 | ||||
-rw-r--r-- | mysql-test/r/partition_pruning.result | 19 | ||||
-rw-r--r-- | mysql-test/t/partition_pruning.test | 19 | ||||
-rw-r--r-- | sql/sql_partition.cc | 32 |
4 files changed, 58 insertions, 14 deletions
diff --git a/mysql-test/r/partition_hash.result b/mysql-test/r/partition_hash.result index 19da70db5a0..dcefd70ff43 100644 --- a/mysql-test/r/partition_hash.result +++ b/mysql-test/r/partition_hash.result @@ -93,7 +93,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where explain partitions select * from t1 where a >= 1 and a <= 5; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p0,p1,p2,p3 ALL NULL NULL NULL NULL 9 Using where +1 SIMPLE t1 p0,p1,p2 ALL NULL NULL NULL NULL 9 Using where drop table t1; CREATE TABLE t1 ( a int not null, diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 769d499fc0a..d8bff2cbe01 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -2229,3 +2229,22 @@ explain partitions select * from t1 where recdate < '2006-01-01 00:00:00'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where drop table t1; +# +# BUG#33730 Full table scan instead selected partitions for query more than 10 partitions +# +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int) +partition by range(a+0) ( +partition p0 values less than (64), +partition p1 values less than (128), +partition p2 values less than (255) +); +insert into t1 select A.a + 10*B.a from t0 A, t0 B; +explain partitions select * from t1 where a between 10 and 13; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 64 Using where +explain partitions select * from t1 where a between 10 and 10+33; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p0,p1,p2 ALL NULL NULL NULL NULL 100 Using where +drop table t0, t1; diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index 11e65be45fc..ea72cef5b62 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -1159,3 +1159,22 @@ INSERT INTO t1 VALUES ('2006-03-01 12:00:00'); -- echo must use p0 only: explain partitions select * from t1 where recdate < '2006-01-01 00:00:00'; drop table t1; + +-- echo # +-- echo # BUG#33730 Full table scan instead selected partitions for query more than 10 partitions +-- echo # +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int) + partition by range(a+0) ( + partition p0 values less than (64), + partition p1 values less than (128), + partition p2 values less than (255) +); +insert into t1 select A.a + 10*B.a from t0 A, t0 B; + +# this will use interval_via_walking +explain partitions select * from t1 where a between 10 and 13; +explain partitions select * from t1 where a between 10 and 10+33; + +drop table t0, t1; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index f6a8e895fdc..a67ed1cf3af 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6850,7 +6850,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, /* See get_part_iter_for_interval_via_walking for definition of what this is */ -#define MAX_RANGE_TO_WALK 10 +#define MAX_RANGE_TO_WALK 32 /* @@ -6886,16 +6886,6 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, Intervals with +inf/-inf, and [NULL, c1] interval can be processed but that is more tricky and I don't have time to do it right now. - Additionally we have these requirements: - * number of values in the interval must be less then number of - [sub]partitions, and - * Number of values in the interval must be less then MAX_RANGE_TO_WALK. - - The rationale behind these requirements is that if they are not met - we're likely to hit most of the partitions and traversing the interval - will only add overhead. So it's better return "all partitions used" in - that case. - RETURN 0 - No matching partitions, iterator not initialized 1 - Some partitions would match, iterator intialized for traversing them @@ -6989,8 +6979,24 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info, a += test(flags & NEAR_MIN); b += test(!(flags & NEAR_MAX)); ulonglong n_values= b - a; - - if (n_values > total_parts || n_values > MAX_RANGE_TO_WALK) + + /* + Will it pay off to enumerate all values in the [a..b] range and evaluate + the partitioning function for every value? It depends on + 1. whether we'll be able to infer that some partitions are not used + 2. if time savings from not scanning these partitions will be greater + than time spent in enumeration. + We will assume that the cost of accessing one extra partition is greater + than the cost of evaluating the partitioning function O(#partitions). + This means we should jump at any chance to eliminate a partition, which + gives us this logic: + + Do the enumeration if + - the number of values to enumerate is comparable to the number of + partitions, or + - there are not many values to enumerate. + */ + if ((n_values > 2*total_parts) && n_values > MAX_RANGE_TO_WALK) return -1; part_iter->field_vals.start= part_iter->field_vals.cur= a; |