Implement cost_of_filesort()
The sort length is extracted similarly to how sortlength() function does it. The function makes use of filesort_use_addons function to compute the length of addon fields. Finally, by calling compute_sort_costs we get the fastest_sort possible. Other changes: * Sort_param::using_addon_fields() assumes addon fields are already allocated. This makes the use of Sort_param unusable for compute_sort_costs *if* we don't want to allocate addon fields. As a preliminary fix, pass "with_addon_fields" as bool value to compute_sort_costs() and make the internal functions use that value instead of Sort_param::using_addon_fields() method. The ideal fix would be to define a "leaner" struct with only the necessary members, but this can be done as a separate commit. Reviewer: Monty
This commit is contained in:
parent
b70290869e
commit
59193ef673
@ -221,6 +221,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
|
|||||||
bool allow_packing_for_sortkeys;
|
bool allow_packing_for_sortkeys;
|
||||||
Bounded_queue<uchar, uchar> pq;
|
Bounded_queue<uchar, uchar> pq;
|
||||||
SQL_SELECT *const select= filesort->select;
|
SQL_SELECT *const select= filesort->select;
|
||||||
|
Sort_costs costs;
|
||||||
ha_rows limit_rows= filesort->limit;
|
ha_rows limit_rows= filesort->limit;
|
||||||
uint s_length= 0, sort_len;
|
uint s_length= 0, sort_len;
|
||||||
Sort_keys *sort_keys;
|
Sort_keys *sort_keys;
|
||||||
@ -266,7 +267,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
|
|||||||
|
|
||||||
param.sort_keys= sort_keys;
|
param.sort_keys= sort_keys;
|
||||||
sort_len= sortlength(thd, sort_keys, &allow_packing_for_sortkeys);
|
sort_len= sortlength(thd, sort_keys, &allow_packing_for_sortkeys);
|
||||||
param.init_for_filesort(sort_len, table, limit_rows, filesort);
|
param.init_for_filesort(table, filesort, sort_len, limit_rows);
|
||||||
if (!param.accepted_rows)
|
if (!param.accepted_rows)
|
||||||
param.accepted_rows= ¬_used;
|
param.accepted_rows= ¬_used;
|
||||||
|
|
||||||
@ -286,7 +287,6 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
|
|||||||
// If number of rows is not known, use as much of sort buffer as possible.
|
// If number of rows is not known, use as much of sort buffer as possible.
|
||||||
num_rows= table->file->estimate_rows_upper_bound();
|
num_rows= table->file->estimate_rows_upper_bound();
|
||||||
|
|
||||||
Sort_costs costs;
|
|
||||||
costs.compute_sort_costs(¶m, num_rows, memory_available,
|
costs.compute_sort_costs(¶m, num_rows, memory_available,
|
||||||
param.using_addon_fields());
|
param.using_addon_fields());
|
||||||
|
|
||||||
|
@ -23,6 +23,13 @@
|
|||||||
|
|
||||||
PSI_memory_key key_memory_Filesort_buffer_sort_keys;
|
PSI_memory_key key_memory_Filesort_buffer_sort_keys;
|
||||||
|
|
||||||
|
const LEX_CSTRING filesort_names[]=
|
||||||
|
{
|
||||||
|
{ STRING_WITH_LEN("priority_queue with addon fields")},
|
||||||
|
{ STRING_WITH_LEN("priority_queue with row lookup")},
|
||||||
|
{ STRING_WITH_LEN("merge_sort with addon fields")},
|
||||||
|
{ STRING_WITH_LEN("merge_sort with row lookup)")}
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Different ways to do sorting:
|
Different ways to do sorting:
|
||||||
@ -51,7 +58,7 @@ PSI_memory_key key_memory_Filesort_buffer_sort_keys;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static
|
static
|
||||||
double get_qsort_sort_cost(size_t num_rows, bool with_addon_fields)
|
double get_qsort_sort_cost(ha_rows num_rows, bool with_addon_fields)
|
||||||
{
|
{
|
||||||
const double row_copy_cost= with_addon_fields ? DEFAULT_ROW_COPY_COST :
|
const double row_copy_cost= with_addon_fields ? DEFAULT_ROW_COPY_COST :
|
||||||
DEFAULT_KEY_COPY_COST;
|
DEFAULT_KEY_COPY_COST;
|
||||||
@ -397,3 +404,66 @@ void Filesort_buffer::sort_buffer(const Sort_param *param, uint count)
|
|||||||
param->get_compare_function(),
|
param->get_compare_function(),
|
||||||
param->get_compare_argument(&size));
|
param->get_compare_argument(&size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
size_t get_sort_length(THD *thd, Item_field *item)
|
||||||
|
{
|
||||||
|
SORT_FIELD_ATTR sort_attr;
|
||||||
|
sort_attr.type= ((item->field)->is_packable() ?
|
||||||
|
SORT_FIELD_ATTR::VARIABLE_SIZE :
|
||||||
|
SORT_FIELD_ATTR::FIXED_SIZE);
|
||||||
|
item->type_handler()->sort_length(thd, item, &sort_attr);
|
||||||
|
|
||||||
|
return sort_attr.length + (item->maybe_null() ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Calculate the cost of doing a filesort
|
||||||
|
|
||||||
|
@param table Table to sort
|
||||||
|
@param Order_by Fields to sort
|
||||||
|
@param rows_to_read Number of rows to be sorted
|
||||||
|
@param limit_rows Number of rows in result (when using limit)
|
||||||
|
@param used_sort_type Set to the sort algorithm used
|
||||||
|
|
||||||
|
@result cost of sorting
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
double cost_of_filesort(TABLE *table, ORDER *order_by, ha_rows rows_to_read,
|
||||||
|
ha_rows limit_rows, enum sort_type *used_sort_type)
|
||||||
|
{
|
||||||
|
THD *thd= table->in_use;
|
||||||
|
Sort_costs costs;
|
||||||
|
Sort_param param;
|
||||||
|
size_t memory_available= (size_t) thd->variables.sortbuff_size;
|
||||||
|
uint sort_len= 0;
|
||||||
|
uint addon_field_length, num_addon_fields, num_nullable_fields;
|
||||||
|
uint packable_length;
|
||||||
|
bool with_addon_fields;
|
||||||
|
|
||||||
|
for (ORDER *ptr= order_by; ptr ; ptr= ptr->next)
|
||||||
|
{
|
||||||
|
Item_field *field= (Item_field*) (*ptr->item)->real_item();
|
||||||
|
size_t length= get_sort_length(table->in_use, field);
|
||||||
|
set_if_smaller(length, thd->variables.max_sort_length);
|
||||||
|
sort_len+= (uint) length;
|
||||||
|
}
|
||||||
|
|
||||||
|
with_addon_fields=
|
||||||
|
filesort_use_addons(table, sort_len, &addon_field_length,
|
||||||
|
&num_addon_fields, &num_nullable_fields,
|
||||||
|
&packable_length);
|
||||||
|
|
||||||
|
/* Fill in the Sort_param structure so we can compute the sort costs */
|
||||||
|
param.setup_lengths_and_limit(table, sort_len, addon_field_length,
|
||||||
|
limit_rows);
|
||||||
|
|
||||||
|
costs.compute_sort_costs(¶m, rows_to_read, memory_available,
|
||||||
|
with_addon_fields);
|
||||||
|
|
||||||
|
*used_sort_type= costs.fastest_sort;
|
||||||
|
return costs.lowest_cost;
|
||||||
|
}
|
||||||
|
@ -19,10 +19,8 @@
|
|||||||
#include "my_global.h"
|
#include "my_global.h"
|
||||||
#include "my_base.h"
|
#include "my_base.h"
|
||||||
#include "sql_array.h"
|
#include "sql_array.h"
|
||||||
|
#include "handler.h"
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
class TABLE;
|
|
||||||
class Sort_param;
|
class Sort_param;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,6 +347,12 @@ private:
|
|||||||
longlong m_idx;
|
longlong m_idx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Names for sort_type */
|
||||||
|
extern const LEX_CSTRING filesort_names[];
|
||||||
|
|
||||||
|
double cost_of_filesort(TABLE *table, ORDER *order_by, ha_rows rows_to_read,
|
||||||
|
ha_rows limit_rows, enum sort_type *used_sort_type);
|
||||||
|
|
||||||
int compare_packed_sort_keys(void *sort_keys, unsigned char **a,
|
int compare_packed_sort_keys(void *sort_keys, unsigned char **a,
|
||||||
unsigned char **b);
|
unsigned char **b);
|
||||||
qsort2_cmp get_packed_keys_compare_ptr();
|
qsort2_cmp get_packed_keys_compare_ptr();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user