Commit 2a3943db authored by sergefp@mysql.com's avatar sergefp@mysql.com

WL#2985 "Partition Pruning": post-review fixes:

- Added more comments.
- Added a RANGE_OPT_PARAM::remove_jump_scans flag that disables construction of index_merge
  SEL_TREEs that represent unusable conditions like "key1part1<c1 OR key2part2<c2"
- make prune_partitions() function handle the case where range analysis produces a list of 
  index_merge trees (it turned out that this is possible, appropriate test case added).
- Other small fixes.
parent e1f49888
...@@ -213,3 +213,48 @@ explain partitions select * from t1 where a='b'; ...@@ -213,3 +213,48 @@ explain partitions select * from t1 where a='b';
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 ALL NULL NULL NULL NULL 3 Using where 1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 3 Using where
drop table t1; drop table t1;
create table t1 (
a1 int not null
)
partition by range (a1) (
partition p0 values less than (3),
partition p1 values less than (6),
partition p2 values less than (9)
);
insert into t1 values (1),(2),(3);
explain partitions select * from t1 where a1 > 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t1 where a1 >= 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t1 where a1 < 3 and a1 > 3;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
drop table t1;
create table t3 (a int, b int)
partition by list(a) subpartition by hash(b) subpartitions 4 (
partition p0 values in (1),
partition p1 values in (2),
partition p2 values in (3),
partition p3 values in (4)
);
insert into t3 values (1,1),(2,2),(3,3);
explain partitions select * from t3 where a=2 or b=1;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t3 p0_sp1,p1_sp0,p1_sp1,p1_sp2,p1_sp3,p2_sp1,p3_sp1 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t3 where a=4 or b=2;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t3 p0_sp2,p1_sp2,p2_sp2,p3_sp0,p3_sp1,p3_sp2,p3_sp3 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t3 where (a=2 or b=1) and (a=4 or b=2) ;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t3 p1_sp2,p3_sp1 ALL NULL NULL NULL NULL 3 Using where
create table t1 (a int) partition by hash(a) partitions 2;
insert into t1 values (1),(2);
explain partitions select * from t1 where a is null;
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
explain partitions select * from t1 where a is not null;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 2 Using where
drop table t1;
...@@ -192,4 +192,46 @@ insert into t1 values ('a'),('b'),('c'); ...@@ -192,4 +192,46 @@ insert into t1 values ('a'),('b'),('c');
explain partitions select * from t1 where a='b'; explain partitions select * from t1 where a='b';
drop table t1; drop table t1;
#
# Test cases for bugs found in code review:
#
create table t1 (
a1 int not null
)
partition by range (a1) (
partition p0 values less than (3),
partition p1 values less than (6),
partition p2 values less than (9)
);
insert into t1 values (1),(2),(3);
explain partitions select * from t1 where a1 > 3;
explain partitions select * from t1 where a1 >= 3;
explain partitions select * from t1 where a1 < 3 and a1 > 3;
drop table t1;
#
create table t3 (a int, b int)
partition by list(a) subpartition by hash(b) subpartitions 4 (
partition p0 values in (1),
partition p1 values in (2),
partition p2 values in (3),
partition p3 values in (4)
);
insert into t3 values (1,1),(2,2),(3,3);
explain partitions select * from t3 where a=2 or b=1;
explain partitions select * from t3 where a=4 or b=2;
explain partitions select * from t3 where (a=2 or b=1) and (a=4 or b=2) ;
# Test for NULLs
create table t1 (a int) partition by hash(a) partitions 2;
insert into t1 values (1),(2);
explain partitions select * from t1 where a is null;
# this selects both
explain partitions select * from t1 where a is not null;
drop table t1;
# No tests for NULLs in RANGE(monotonic_expr()) - they depend on BUG#15447
# being fixed.
This diff is collapsed.
...@@ -2493,8 +2493,9 @@ bool get_partition_id_list(partition_info *part_info, ...@@ -2493,8 +2493,9 @@ bool get_partition_id_list(partition_info *part_info,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
/* /*
Find the part of part_info->list_array that corresponds to given interval Find the sub-array part_info->list_array that corresponds to given interval
SYNOPSIS SYNOPSIS
get_list_array_idx_for_endpoint() get_list_array_idx_for_endpoint()
...@@ -2504,17 +2505,16 @@ bool get_partition_id_list(partition_info *part_info, ...@@ -2504,17 +2505,16 @@ bool get_partition_id_list(partition_info *part_info,
include_endpoint TRUE iff the interval includes the endpoint include_endpoint TRUE iff the interval includes the endpoint
DESCRIPTION DESCRIPTION
This function finds the part of part_info->list_array where values of This function finds the sub-array of part_info->list_array where values of
list_array[idx].list_value are contained within the specifed interval. list_array[idx].list_value are contained within the specifed interval.
list_array is ordered by list_value, so list_array is ordered by list_value, so
1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the 1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
sought array part starts at some index idx and continues till array sought sub-array starts at some index idx and continues till array end.
end.
The function returns first number idx, such that The function returns first number idx, such that
list_array[idx].list_value is contained within the passed interval. list_array[idx].list_value is contained within the passed interval.
2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the 2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
sought array part starts at array start and continues till some last sought sub-array starts at array start and continues till some last
index idx. index idx.
The function returns first number idx, such that The function returns first number idx, such that
list_array[idx].list_value is NOT contained within the passed interval. list_array[idx].list_value is NOT contained within the passed interval.
...@@ -2522,14 +2522,14 @@ bool get_partition_id_list(partition_info *part_info, ...@@ -2522,14 +2522,14 @@ bool get_partition_id_list(partition_info *part_info,
returned. returned.
NOTE NOTE
The caller will call this function and then will run along the part of The caller will call this function and then will run along the sub-array of
list_array to collect partition ids. If the number of list values is list_array to collect partition ids. If the number of list values is
significantly higher then number of partitions, this could be slow and significantly higher then number of partitions, this could be slow and
we could invent some other approach. The "run over list array" part is we could invent some other approach. The "run over list array" part is
already wrapped in a get_next()-like function. already wrapped in a get_next()-like function.
RETURN RETURN
The edge of corresponding part_info->list_array part. The edge of corresponding sub-array of part_info->list_array
*/ */
uint32 get_list_array_idx_for_endpoint(partition_info *part_info, uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
...@@ -2541,6 +2541,7 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, ...@@ -2541,6 +2541,7 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
uint list_index; uint list_index;
longlong list_value; longlong list_value;
uint min_list_index= 0, max_list_index= part_info->no_list_values - 1; uint min_list_index= 0, max_list_index= part_info->no_list_values - 1;
/* Get the partitioning function value for the endpoint */
longlong part_func_value= part_info->part_expr->val_int(); longlong part_func_value= part_info->part_expr->val_int();
while (max_list_index >= min_list_index) while (max_list_index >= min_list_index)
{ {
...@@ -2596,7 +2597,7 @@ bool get_partition_id_range(partition_info *part_info, ...@@ -2596,7 +2597,7 @@ bool get_partition_id_range(partition_info *part_info,
/* /*
Find the part of part_info->range_int_array that covers the given interval Find the sub-array of part_info->range_int_array that covers given interval
SYNOPSIS SYNOPSIS
get_partition_id_range_for_endpoint() get_partition_id_range_for_endpoint()
...@@ -2607,7 +2608,7 @@ bool get_partition_id_range(partition_info *part_info, ...@@ -2607,7 +2608,7 @@ bool get_partition_id_range(partition_info *part_info,
interval interval
DESCRIPTION DESCRIPTION
This function finds the part of part_info->range_int_array where the This function finds the sub-array of part_info->range_int_array where the
elements have non-empty intersections with the given interval. elements have non-empty intersections with the given interval.
A range_int_array element at index idx represents the interval A range_int_array element at index idx represents the interval
...@@ -2617,14 +2618,13 @@ bool get_partition_id_range(partition_info *part_info, ...@@ -2617,14 +2618,13 @@ bool get_partition_id_range(partition_info *part_info,
intervals are disjoint and ordered by their right bound, so intervals are disjoint and ordered by their right bound, so
1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the 1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
sought array part starts at some index idx and continues till array sought sub-array starts at some index idx and continues till array end.
end.
The function returns first number idx, such that the interval The function returns first number idx, such that the interval
represented by range_int_array[idx] has non empty intersection with represented by range_int_array[idx] has non empty intersection with
the passed interval. the passed interval.
2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the 2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
sought array part starts at array start and continues till some last sought sub-array starts at array start and continues till some last
index idx. index idx.
The function returns first number idx, such that the interval The function returns first number idx, such that the interval
represented by range_int_array[idx] has EMPTY intersection with the represented by range_int_array[idx] has EMPTY intersection with the
...@@ -2634,7 +2634,7 @@ bool get_partition_id_range(partition_info *part_info, ...@@ -2634,7 +2634,7 @@ bool get_partition_id_range(partition_info *part_info,
returned. returned.
RETURN RETURN
The edge of corresponding part_info->range_int_array part. The edge of corresponding part_info->range_int_array sub-array.
*/ */
uint32 get_partition_id_range_for_endpoint(partition_info *part_info, uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
...@@ -2645,6 +2645,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, ...@@ -2645,6 +2645,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
longlong *range_array= part_info->range_int_array; longlong *range_array= part_info->range_int_array;
uint max_partition= part_info->no_parts - 1; uint max_partition= part_info->no_parts - 1;
uint min_part_id= 0, max_part_id= max_partition, loc_part_id; uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
/* Get the partitioning function value for the endpoint */
longlong part_func_value= part_info->part_expr->val_int(); longlong part_func_value= part_info->part_expr->val_int();
while (max_part_id > min_part_id) while (max_part_id > min_part_id)
{ {
......
...@@ -297,6 +297,7 @@ struct st_table { ...@@ -297,6 +297,7 @@ struct st_table {
FILESORT_INFO sort; FILESORT_INFO sort;
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info; /* Partition related information */ partition_info *part_info; /* Partition related information */
bool no_partitions_used; /* If true, all partitions have been pruned away */
#endif #endif
bool fill_item_list(List<Item> *item_list) const; bool fill_item_list(List<Item> *item_list) const;
......
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