Commit 56312dc7 authored by Guilhem Bichot's avatar Guilhem Bichot

Backport of the fix for BUG#33730 "Full table scan instead selected partitions...

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
parent 42e80778
...@@ -93,7 +93,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra ...@@ -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 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; 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 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; drop table t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
a int not null, a int not null,
......
...@@ -2229,3 +2229,22 @@ explain partitions select * from t1 where recdate < '2006-01-01 00:00:00'; ...@@ -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 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 1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
drop table t1; 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;
...@@ -1159,3 +1159,22 @@ INSERT INTO t1 VALUES ('2006-03-01 12:00:00'); ...@@ -1159,3 +1159,22 @@ INSERT INTO t1 VALUES ('2006-03-01 12:00:00');
-- echo must use p0 only: -- echo must use p0 only:
explain partitions select * from t1 where recdate < '2006-01-01 00:00:00'; explain partitions select * from t1 where recdate < '2006-01-01 00:00:00';
drop table t1; 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;
...@@ -6850,7 +6850,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, ...@@ -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 */ /* 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, ...@@ -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 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. 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 RETURN
0 - No matching partitions, iterator not initialized 0 - No matching partitions, iterator not initialized
1 - Some partitions would match, iterator intialized for traversing them 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, ...@@ -6989,8 +6979,24 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
a += test(flags & NEAR_MIN); a += test(flags & NEAR_MIN);
b += test(!(flags & NEAR_MAX)); b += test(!(flags & NEAR_MAX));
ulonglong n_values= b - a; 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; return -1;
part_iter->field_vals.start= part_iter->field_vals.cur= a; part_iter->field_vals.start= part_iter->field_vals.cur= a;
......
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