1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

WL#2985 "Partition Pruning"

This commit is contained in:
sergefp@mysql.com
2005-12-22 12:29:00 +03:00
parent 7100dec8fe
commit e1f49888bf
15 changed files with 1743 additions and 48 deletions

View File

@ -2477,16 +2477,94 @@ bool get_partition_id_list(partition_info *part_info,
if (list_value < part_func_value)
min_list_index= list_index + 1;
else if (list_value > part_func_value)
{
if (!list_index)
goto notfound;
max_list_index= list_index - 1;
else {
}
else
{
*part_id= (uint32)list_array[list_index].partition_id;
DBUG_RETURN(FALSE);
}
}
notfound:
*part_id= 0;
DBUG_RETURN(TRUE);
}
/*
Find the part of part_info->list_array that corresponds to given interval
SYNOPSIS
get_list_array_idx_for_endpoint()
part_info Partitioning info (partitioning type must be LIST)
left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
FALSE - the interval is (-inf; a] or (-inf; a)
include_endpoint TRUE iff the interval includes the endpoint
DESCRIPTION
This function finds the part of part_info->list_array where values of
list_array[idx].list_value are contained within the specifed interval.
list_array is ordered by list_value, so
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
end.
The function returns first number idx, such that
list_array[idx].list_value is contained within the passed interval.
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
index idx.
The function returns first number idx, such that
list_array[idx].list_value is NOT contained within the passed interval.
If all array elements are contained, part_info->no_list_values is
returned.
NOTE
The caller will call this function and then will run along the part of
list_array to collect partition ids. If the number of list values is
significantly higher then number of partitions, this could be slow and
we could invent some other approach. The "run over list array" part is
already wrapped in a get_next()-like function.
RETURN
The edge of corresponding part_info->list_array part.
*/
uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
bool left_endpoint,
bool include_endpoint)
{
DBUG_ENTER("get_list_array_idx_for_endpoint");
LIST_PART_ENTRY *list_array= part_info->list_array;
uint list_index;
longlong list_value;
uint min_list_index= 0, max_list_index= part_info->no_list_values - 1;
longlong part_func_value= part_info->part_expr->val_int();
while (max_list_index >= min_list_index)
{
list_index= (max_list_index + min_list_index) >> 1;
list_value= list_array[list_index].list_value;
if (list_value < part_func_value)
min_list_index= list_index + 1;
else if (list_value > part_func_value)
{
if (!list_index)
goto notfound;
max_list_index= list_index - 1;
}
else
{
DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint));
}
}
notfound:
if (list_value < part_func_value)
list_index++;
DBUG_RETURN(list_index);
}
bool get_partition_id_range(partition_info *part_info,
uint32 *part_id)
@ -2516,6 +2594,89 @@ bool get_partition_id_range(partition_info *part_info,
DBUG_RETURN(FALSE);
}
/*
Find the part of part_info->range_int_array that covers the given interval
SYNOPSIS
get_partition_id_range_for_endpoint()
part_info Partitioning info (partitioning type must be RANGE)
left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
FALSE - the interval is (-inf; a] or (-inf; a).
include_endpoint TRUE <=> the endpoint itself is included in the
interval
DESCRIPTION
This function finds the part of part_info->range_int_array where the
elements have non-empty intersections with the given interval.
A range_int_array element at index idx represents the interval
[range_int_array[idx-1], range_int_array[idx]),
intervals are disjoint and ordered by their right bound, so
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
end.
The function returns first number idx, such that the interval
represented by range_int_array[idx] has non empty intersection with
the passed interval.
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
index idx.
The function returns first number idx, such that the interval
represented by range_int_array[idx] has EMPTY intersection with the
passed interval.
If the interval represented by the last array element has non-empty
intersection with the passed interval, part_info->no_parts is
returned.
RETURN
The edge of corresponding part_info->range_int_array part.
*/
uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
bool left_endpoint,
bool include_endpoint)
{
DBUG_ENTER("get_partition_id_range_for_endpoint");
longlong *range_array= part_info->range_int_array;
uint max_partition= part_info->no_parts - 1;
uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
longlong part_func_value= part_info->part_expr->val_int();
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)
min_part_id= loc_part_id + 1;
else
max_part_id= loc_part_id - 1;
}
loc_part_id= max_part_id;
if (loc_part_id < max_partition &&
part_func_value >= range_array[loc_part_id+1])
{
loc_part_id++;
}
if (left_endpoint)
{
if (part_func_value >= range_array[loc_part_id])
loc_part_id++;
}
else
{
if (part_func_value == range_array[loc_part_id])
loc_part_id += test(include_endpoint);
else if (part_func_value > range_array[loc_part_id])
loc_part_id++;
loc_part_id++;
}
DBUG_RETURN(loc_part_id);
}
bool get_partition_id_hash_nosub(partition_info *part_info,
uint32 *part_id)
{
@ -3204,10 +3365,16 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
*/
uint part_func_len= part_info->part_func_len;
uint subpart_func_len= part_info->subpart_func_len;
uint bitmap_bits= part_info->no_subparts?
(part_info->no_subparts* part_info->no_parts):
part_info->no_parts;
uint bitmap_bytes= bitmap_buffer_size(bitmap_bits);
uint32 *bitmap_buf;
char *part_func_string, *subpart_func_string= NULL;
if (!((part_func_string= thd->alloc(part_func_len))) ||
(subpart_func_len &&
!((subpart_func_string= thd->alloc(subpart_func_len)))))
!((subpart_func_string= thd->alloc(subpart_func_len)))) ||
!((bitmap_buf= (uint32*)thd->alloc(bitmap_bytes))))
{
my_error(ER_OUTOFMEMORY, MYF(0), part_func_len);
free_items(thd->free_list);
@ -3220,6 +3387,8 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
subpart_func_len);
part_info->part_func_string= part_func_string;
part_info->subpart_func_string= subpart_func_string;
bitmap_init(&part_info->used_partitions, bitmap_buf, bitmap_bytes*8, FALSE);
}
result= FALSE;
@ -3293,3 +3462,60 @@ void set_key_field_ptr(KEY *key_info, const byte *new_buf,
} while (++i < key_parts);
DBUG_VOID_RETURN;
}
/*
Fill the string comma-separated line of used partitions names
SYNOPSIS
make_used_partitions_str()
part_info IN Partitioning info
parts_str OUT The string to fill
*/
void make_used_partitions_str(partition_info *part_info, String *parts_str)
{
parts_str->length(0);
partition_element *pe;
uint partition_id= 0;
List_iterator<partition_element> it(part_info->partitions);
if (part_info->subpart_type != NOT_A_PARTITION)
{
partition_element *head_pe;
while ((head_pe= it++))
{
List_iterator<partition_element> it2(head_pe->subpartitions);
while ((pe= it2++))
{
if (bitmap_is_set(&part_info->used_partitions, partition_id))
{
if (parts_str->length())
parts_str->append(',');
parts_str->append(head_pe->partition_name,
strlen(head_pe->partition_name),
system_charset_info);
parts_str->append('_');
parts_str->append(pe->partition_name,
strlen(pe->partition_name),
system_charset_info);
}
partition_id++;
}
}
}
else
{
while ((pe= it++))
{
if (bitmap_is_set(&part_info->used_partitions, partition_id))
{
if (parts_str->length())
parts_str->append(',');
parts_str->append(pe->partition_name, strlen(pe->partition_name),
system_charset_info);
}
partition_id++;
}
}
}