Commit 13ee3410 authored by unknown's avatar unknown

WL# 2986

Final patch
-----------

This WL is about using this bitmap in all parts of the partition handler.
Thus for:
rnd_init/rnd_next
index_init/index_next and all other variants of index scans
read_range_... the various range scans implemented in the partition handler.

Also use those bitmaps in the various other calls that currently loop over all
partitions.




mysql-test/r/partition_pruning.result:
  WL# 2986
  
  New results reflecting bitmap being used to determine if a partition is to be
  included
mysql-test/t/partition_pruning.test:
  WL# 2986
  
  New tests to show bitmap being used in ha_partition
sql/ha_partition.cc:
  WL# 2986
  
  Used work from 2682 and removed the partition select code.
      
  Added do {} while loop to any iteration over partitions to now utilise 
  m_part_info->used_partitions bitmap to determine if a partition should be
  used.
sql/ha_partition.h:
  WL# 2986
  
  Removed unused member
sql/handler.h:
  WL# 2986
  
  Removed unused member
sql/opt_range.cc:
  WL# 2986
  
  Added bitmap_clear_all to clear bitmap prior to pruning
  DBUG code for testing
sql/sql_partition.cc:
  WL# 2986
  
  Changed < to <=, which fixes the problem with edge cases going awry.
parent 29ac2b8d
This diff is collapsed.
......@@ -270,5 +270,137 @@ insert into t1 values (1,1),(2,2),(3,3);
explain partitions select * from t1 where b > 1 and b < 3;
explain partitions select * from t1 where b > 1 and b < 3 and (a =1 or a =2);
# WL# 2986
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`a` int(11) default NULL
);
INSERT INTO t1 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
DROP TABLE IF EXISTS `t2`;
CREATE TABLE `t2` (
`a` int(11) default NULL,
KEY `a` (`a`)
) ;
insert into t2 select A.a + 10*(B.a + 10* C.a) from t1 A, t1 B, t1 C ;
insert into t1 select a from t2;
DROP TABLE IF EXISTS `t2`;
CREATE TABLE `t2` (
`a` int(11) default NULL,
`b` int(11) default NULL
)
PARTITION BY RANGE (a) (
PARTITION p0 VALUES LESS THAN (200),
PARTITION p1 VALUES LESS THAN (400),
PARTITION p2 VALUES LESS THAN (600),
PARTITION p3 VALUES LESS THAN (800),
PARTITION p4 VALUES LESS THAN (1001));
insert into t2 select a,1 from t1 where a < 200;
insert into t2 select a,2 from t1 where a >= 200 and a < 400;
insert into t2 select a,3 from t1 where a >= 400 and a < 600;
insert into t2 select a,4 from t1 where a >= 600 and a < 800;
insert into t2 select a,5 from t1 where a >= 800 and a < 1001;
explain partitions select * from t2;
explain partitions select * from t2 where a < 801 and a > 200;
explain partitions select * from t2 where a < 801 and a > 800;
explain partitions select * from t2 where a > 600;
explain partitions select * from t2 where a > 600 and b = 1;
explain partitions select * from t2 where a > 600 and b = 4;
explain partitions select * from t2 where a > 600 and b = 5;
explain partitions select * from t2 where b = 5;
flush status;
update t2 set b = 100 where b = 6;
show status like 'Handler_read_rnd_next';
flush status;
update t2 set a = 1002 where a = 1001;
show status like 'Handler_read_rnd_next';
flush status;
update t2 set b = 6 where a = 600;
show status like 'Handler_read_rnd_next';
flush status;
update t2 set b = 6 where a > 600 and a < 800;
show status like 'Handler_read_rnd_next';
flush status;
delete from t2 where a > 600;
show status like 'Handler_read_rnd_next';
DROP TABLE IF EXISTS `t2`;
CREATE TABLE `t2` (
`a` int(11) default NULL,
`b` int(11) default NULL,
index (b)
)
PARTITION BY RANGE (a) (
PARTITION p0 VALUES LESS THAN (200),
PARTITION p1 VALUES LESS THAN (400),
PARTITION p2 VALUES LESS THAN (600),
PARTITION p3 VALUES LESS THAN (800),
PARTITION p4 VALUES LESS THAN (1001));
insert into t2 select a,1 from t1 where a < 100;
insert into t2 select a,2 from t1 where a >= 200 and a < 300;
insert into t2 select a,3 from t1 where a >= 300 and a < 400;
insert into t2 select a,4 from t1 where a >= 400 and a < 500;
insert into t2 select a,5 from t1 where a >= 500 and a < 600;
insert into t2 select a,6 from t1 where a >= 600 and a < 700;
insert into t2 select a,7 from t1 where a >= 700 and a < 800;
insert into t2 select a,8 from t1 where a >= 800 and a < 900;
insert into t2 select a,9 from t1 where a >= 900 and a < 1001;
explain partitions select * from t2;
# not using indexes
explain partitions select * from t2 where a = 101;
explain partitions select * from t2 where a = 550;
explain partitions select * from t2 where a = 833;
explain partitions select * from t2 where (a = 100 OR a = 900);
explain partitions select * from t2 where (a > 100 AND a < 600);
explain partitions select * from t2 where b = 4;
explain partitions select * from t2 where b = 6;
explain partitions select * from t2 where b in (1,3,5);
explain partitions select * from t2 where b in (2,4,6);
explain partitions select * from t2 where b in (7,8,9);
explain partitions select * from t2 where b > 5;
explain partitions select * from t2 where b > 5 and b < 8;
explain partitions select * from t2 where b > 5 and b < 7;
explain partitions select * from t2 where b > 0 and b < 5;
flush status;
update t2 set a = 111 where b = 10;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
flush status;
update t2 set a = 111 where b in (5,6);
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
flush status;
update t2 set a = 222 where b = 7;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
flush status;
delete from t2 where b = 7;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
flush status;
delete from t2 where b > 5;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
show status like 'Handler_read_prev';
show status like 'Handler_read_next';
flush status;
delete from t2 where b < 5 or b > 3;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
show status like 'Handler_read_prev';
show status like 'Handler_read_next';
drop table t1, t2;
# No tests for NULLs in RANGE(monotonic_expr()) - they depend on BUG#15447
# being fixed.
This diff is collapsed.
......@@ -100,7 +100,6 @@ class ha_partition :public handler
bool m_create_handler; // Handler used to create table
bool m_is_sub_partitioned; // Is subpartitioned
bool m_ordered_scan_ongoing;
bool m_use_bit_array;
/*
We keep track if all underlying handlers are MyISAM since MyISAM has a
......
......@@ -618,7 +618,6 @@ enum ndb_distribution { ND_KEYHASH= 0, ND_LINHASH= 1 };
typedef struct {
uint32 start_part;
uint32 end_part;
bool use_bit_array;
} part_id_range;
......
......@@ -2309,7 +2309,9 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
thd->no_errors=1; // Don't warn about NULL
thd->mem_root=&alloc;
bitmap_clear_all(&part_info->used_partitions);
prune_param.key= prune_param.range_param.key_parts;
SEL_TREE *tree;
SEL_ARG *arg;
......@@ -2453,7 +2455,10 @@ static void store_selargs_to_rec(PART_PRUNE_PARAM *ppar, SEL_ARG **start,
static void mark_full_partition_used_no_parts(partition_info* part_info,
uint32 part_id)
{
DBUG_ENTER("mark_full_partition_used_no_parts");
DBUG_PRINT("enter", ("Mark partition %u as used", part_id));
bitmap_set_bit(&part_info->used_partitions, part_id);
DBUG_VOID_RETURN;
}
......@@ -2463,8 +2468,14 @@ static void mark_full_partition_used_with_parts(partition_info *part_info,
{
uint32 start= part_id * part_info->no_subparts;
uint32 end= start + part_info->no_subparts;
DBUG_ENTER("mark_full_partition_used_with_parts");
for (; start != end; start++)
{
DBUG_PRINT("info", ("1:Mark subpartition %u as used", start));
bitmap_set_bit(&part_info->used_partitions, start);
}
DBUG_VOID_RETURN;
}
/*
......@@ -2495,7 +2506,7 @@ static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar,
if (!(bitmap_buf= (uint32*)alloc_root(ppar->range_param.mem_root,
bitmap_bytes)))
{
/*
/*
Fallback, process just the first SEL_IMERGE. This can leave us with more
partitions marked as used then actually needed.
*/
......@@ -2503,7 +2514,7 @@ static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar,
}
bitmap_init(&all_merges, bitmap_buf, n_bits, FALSE);
bitmap_set_prefix(&all_merges, n_bits);
List_iterator<SEL_IMERGE> it(merges);
SEL_IMERGE *imerge;
while ((imerge=it++))
......@@ -2514,7 +2525,7 @@ static int find_used_partitions_imerge_list(PART_PRUNE_PARAM *ppar,
/* no used partitions on one ANDed imerge => no used partitions at all */
return 0;
}
if (res != -1)
bitmap_intersect(&all_merges, &ppar->part_info->used_partitions);
......
......@@ -3004,7 +3004,7 @@ int get_partition_id_range(partition_info *part_info,
while (max_part_id > min_part_id)
{
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
if (range_array[loc_part_id] < part_func_value)
if (range_array[loc_part_id] <= part_func_value)
min_part_id= loc_part_id + 1;
else
max_part_id= loc_part_id - 1;
......@@ -3077,7 +3077,7 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
while (max_part_id > min_part_id)
{
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
if (range_array[loc_part_id] < part_func_value)
if (range_array[loc_part_id] <= part_func_value)
min_part_id= loc_part_id + 1;
else
max_part_id= loc_part_id - 1;
......@@ -3639,7 +3639,6 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
bool found_part_field= FALSE;
DBUG_ENTER("get_partition_set");
part_spec->use_bit_array= FALSE;
part_spec->start_part= 0;
part_spec->end_part= no_parts - 1;
if ((index < MAX_KEY) &&
......@@ -3757,7 +3756,6 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
else
{
DBUG_ASSERT(sub_part != no_parts);
part_spec->use_bit_array= TRUE;
part_spec->start_part= sub_part;
part_spec->end_part=sub_part+
(part_info->no_subparts*(part_info->no_parts-1));
......
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