Skip to content

Commit

Permalink
Implement cost_of_filesort()
Browse files Browse the repository at this point in the history
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
  • Loading branch information
cvicentiu authored and spetrunia committed Feb 2, 2023
1 parent b702908 commit 59193ef
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 6 deletions.
4 changes: 2 additions & 2 deletions sql/filesort.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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());

Expand Down
72 changes: 71 additions & 1 deletion sql/filesort_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
10 changes: 7 additions & 3 deletions sql/filesort_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 59193ef

Please sign in to comment.