Commit 59193ef6 authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru Committed by Sergei Petrunia

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
parent b7029086
......@@ -221,6 +221,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
bool allow_packing_for_sortkeys;
Bounded_queue<uchar, uchar> pq;
SQL_SELECT *const select= filesort->select;
Sort_costs costs;
ha_rows limit_rows= filesort->limit;
uint s_length= 0, sort_len;
Sort_keys *sort_keys;
......@@ -266,7 +267,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
param.sort_keys= sort_keys;
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)
param.accepted_rows= &not_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.
num_rows= table->file->estimate_rows_upper_bound();
Sort_costs costs;
costs.compute_sort_costs(&param, num_rows, memory_available,
param.using_addon_fields());
......
......@@ -23,6 +23,13 @@
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:
......@@ -51,7 +58,7 @@ PSI_memory_key key_memory_Filesort_buffer_sort_keys;
*/
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 :
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_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(&param, 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_base.h"
#include "sql_array.h"
#include "handler.h"
#include <utility>
class TABLE;
class Sort_param;
/**
......@@ -349,6 +347,12 @@ class Filesort_buffer
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,
unsigned char **b);
qsort2_cmp get_packed_keys_compare_ptr();
......
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