1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00
Files
mariadb/sql/filesort.h
bsrikanth-mariadb 85595ce69c MDEV-36523: Load basic stats from trace into optimizer
This task loads the stats of the tables that are used in a query,
from the trace into the optimizer. This feature is controlled
by optimizer_replay_context, and points to an user defined variable name,
that has the context information.
The stats such as num_of_records present in the table, indexes if present,
their names, along with the average number of records_per_key
with in each index, cost of reading an index are loaded from the trace.
Additionally, stats from range analysis i.e. ranges, and the
corresponding number of records, along with their costs are also
loaded from the trace.

The trace context which is in JSON format is firstly set into the
user defined session variable, and this variable name is set to
optimizer_replay_context system variable.
Later, when a user issues a query, the contents of the json context is
parsed and an in memory representation is built using the class
Optimizer_context_replay. This class is then used by the optimizer
to update and save original values of the tables, indexes, and range stats
in the methods "set_statistics_for_table()" of sql_statistics.cc, and
"check_quick_select()" of opt_range.cc.
After the query gets finished, the statistics that were updated
in the optimizer are restored back to the saved original values.

The entry point for parsing the json structure is in
"mysql_execute_command()" of sql_parse.cc, and similarly exit point
i.e. to restore the saved stats of the optimizer is at the end
of the same method.

Two new warning/error messages are introduced:
ER_JSON_OPTIMIZER_REPLAY_CONTEXT_PARSE_FAILED, and
ER_JSON_OPTIMIZER_REPLAY_CONTEXT_MATCH_FAILED
2026-08-12 14:31:52 +03:00

251 lines
7.3 KiB
C++

/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef FILESORT_INCLUDED
#define FILESORT_INCLUDED
#include "my_base.h" /* ha_rows */
#include "sql_alloc.h"
#include "filesort_utils.h"
class SQL_SELECT;
class THD;
struct TABLE;
class Filesort_tracker;
struct SORT_FIELD;
struct SORT_FIELD_ATTR;
typedef struct st_order ORDER;
class JOIN;
class Addon_fields;
class Sort_keys;
/**
Sorting related info.
To be extended by another WL to include complete filesort implementation.
*/
class Filesort: public Sql_alloc
{
public:
/** List of expressions to order the table by */
ORDER *order;
/** Number of records to return */
ha_rows limit;
/** ORDER BY list with some precalculated info for filesort */
SORT_FIELD *sortorder;
/* Used with ROWNUM. Contains the number of rows filesort has found so far */
ha_rows *accepted_rows;
/** select to use for getting records */
SQL_SELECT *select;
/** TRUE <=> free select on destruction */
bool own_select;
/** TRUE means we are using Priority Queue for order by with limit. */
bool using_pq;
/*
TRUE means sort operation must produce table rowids.
FALSE means that it also has an option of producing {sort_key, addon_fields}
pairs.
Usually initialized with value of join_tab->keep_current_rowid to allow for
a call to table->file->position() using these table rowids.
*/
bool sort_positions;
/*
TRUE means all the fields of table of whose bitmap read_set is set
need to be read while reading records in the sort buffer.
FALSE otherwise
*/
bool set_all_read_bits;
Filesort_tracker *tracker;
Sort_keys *sort_keys;
/* Unpack temp table columns to base table columns*/
void (*unpack)(TABLE *);
Filesort(ORDER *order_arg, ha_rows limit_arg, bool sort_positions_arg,
SQL_SELECT *select_arg):
order(order_arg),
limit(limit_arg),
sortorder(NULL),
accepted_rows(0),
select(select_arg),
own_select(false),
using_pq(false),
sort_positions(sort_positions_arg),
set_all_read_bits(false),
sort_keys(NULL),
unpack(NULL)
{
DBUG_ASSERT(order);
};
~Filesort() { cleanup(); }
/* Prepare ORDER BY list for sorting. */
Sort_keys* make_sortorder(THD *thd, JOIN *join, table_map first_table_bit);
private:
void cleanup();
};
class SORT_INFO
{
/// Buffer for sorting keys.
Filesort_buffer filesort_buffer;
public:
SORT_INFO()
:addon_fields(NULL), record_pointers(0),
sort_keys(NULL),
sorted_result_in_fsbuf(FALSE)
{
buffpek.str= 0;
my_b_clear(&io_cache);
}
~SORT_INFO();
void free_data()
{
close_cached_file(&io_cache);
free_addon_buff();
my_free(record_pointers);
my_free(buffpek.str);
my_free(addon_fields);
free_sort_buffer();
}
void reset()
{
free_data();
record_pointers= 0;
buffpek.str= 0;
addon_fields= 0;
sorted_result_in_fsbuf= false;
}
void free_addon_buff();
IO_CACHE io_cache; /* If sorted through filesort */
LEX_STRING buffpek; /* Buffer for buffpek structures */
Addon_fields *addon_fields; /* Addon field descriptors */
uchar *record_pointers; /* If sorted in memory */
Sort_keys *sort_keys; /* Sort key descriptors*/
/**
If the entire result of filesort fits in memory, we skip the merge phase.
We may leave the result in filesort_buffer
(indicated by sorted_result_in_fsbuf), or we may strip away
the sort keys, and copy the sorted result into a new buffer.
@see save_index()
*/
bool sorted_result_in_fsbuf;
/*
How many rows in final result.
Also how many rows in record_pointers, if used
*/
ha_rows return_rows;
ha_rows m_examined_rows; /* How many rows read. Already in thd */
ha_rows found_rows; /* How many rows was accepted */
/** Sort filesort_buffer */
void sort_buffer(Sort_param *param, uint count)
{ filesort_buffer.sort_buffer(param, count); }
uchar **get_sort_keys()
{ return filesort_buffer.get_sort_keys(); }
uchar *get_sorted_record(uint ix)
{ return filesort_buffer.get_sorted_record(ix); }
uchar *alloc_sort_buffer(uint num_records, uint record_length)
{ return filesort_buffer.alloc_sort_buffer(num_records, record_length); }
void free_sort_buffer()
{ filesort_buffer.free_sort_buffer(); }
bool isfull() const
{ return filesort_buffer.isfull(); }
void init_record_pointers()
{ filesort_buffer.init_record_pointers(); }
void init_next_record_pointer()
{ filesort_buffer.init_next_record_pointer(); }
uchar *get_next_record_pointer()
{ return filesort_buffer.get_next_record_pointer(); }
void adjust_next_record_pointer(uint val)
{ filesort_buffer.adjust_next_record_pointer(val); }
Bounds_checked_array<uchar> get_raw_buf()
{ return filesort_buffer.get_raw_buf(); }
size_t sort_buffer_size() const
{ return filesort_buffer.sort_buffer_size(); }
bool is_allocated() const
{ return filesort_buffer.is_allocated(); }
void set_sort_length(uint val)
{ filesort_buffer.set_sort_length(val); }
uint get_sort_length() const
{ return filesort_buffer.get_sort_length(); }
bool has_filesort_result_in_memory() const
{
return record_pointers || sorted_result_in_fsbuf;
}
/// Are we using "addon fields"?
bool using_addon_fields() const
{
return addon_fields != NULL;
}
/// Are we using "packed addon fields"?
bool using_packed_addons();
/**
Copies (unpacks) values appended to sorted fields from a buffer back to
their regular positions specified by the Field::ptr pointers.
@param buff Buffer which to unpack the value from
*/
template<bool Packed_addon_fields>
inline void unpack_addon_fields(uchar *buff);
bool using_packed_sortkeys();
friend SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
Filesort_tracker* tracker, JOIN *join,
table_map first_table_bit);
};
SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
Filesort_tracker* tracker, JOIN *join=NULL,
table_map first_table_bit=0);
bool filesort_use_addons(TABLE *table, uint sortlength,
uint *length, uint *fields, uint *null_fields,
uint *m_packable_length);
void change_double_for_sort(double nr,uchar *to);
void store_length(uchar *to, uint length, uint pack_length);
void
reverse_key(uchar *to, const SORT_FIELD_ATTR *sort_field);
void format_and_store_row(TABLE *table, const uchar *rec, bool print_names,
const char *separator, bool reqd_table_alias,
String &output);
#endif /* FILESORT_INCLUDED */