1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge 11.0 into 11.1

This commit is contained in:
Marko Mäkelä
2024-03-28 12:15:36 +02:00
727 changed files with 22650 additions and 8324 deletions

View File

@@ -3200,6 +3200,53 @@ SQL_SELECT::test_quick_select(THD *thd,
****************************************************************************/
/*
@brief
Create a bitmap of columns for which to perform Range Analysis for EITS
condition selectivity estimates.
@detail
Walk through the bitmap of fields used in the query, and
- pick columns for which EITS data is usable (see is_eits_usable() call)
- do not produce more than MAX_KEY columns. Range Analyzer cannot handle
more than that. If there are more than MAX_KEY eligible columns,
this function should be called multiple times to produce multiple
bitmaps.
@param used_fields Columns used by the query
@param col_no Start from this column
@param out OUT Filled column bitmap
@return
(uint)-1 If there are no more columns for range analysis.
Other Index of the last considered column. Pass this to next call to
this function
*/
uint get_columns_for_pseudo_indexes(const TABLE *table,
const MY_BITMAP *used_fields, int col_no,
MY_BITMAP *out)
{
bitmap_clear_all(out);
int n_bits= 0;
for (; table->field[col_no]; col_no++)
{
if (bitmap_is_set(used_fields, col_no) &&
is_eits_usable(table->field[col_no]))
{
bitmap_set_bit(out, col_no);
if (++n_bits == MAX_KEY)
{
col_no++;
break;
}
}
}
return n_bits? col_no: (uint)-1;
}
/*
Build descriptors of pseudo-indexes over columns to perform range analysis
@@ -3225,22 +3272,11 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
{
Field **field_ptr;
TABLE *table= param->table;
uint parts= 0;
for (field_ptr= table->field; *field_ptr; field_ptr++)
{
Field *field= *field_ptr;
if (bitmap_is_set(used_fields, field->field_index) &&
is_eits_usable(field))
parts++;
}
uint parts= bitmap_bits_set(used_fields);
KEY_PART *key_part;
uint keys= 0;
if (!parts)
return TRUE;
if (!(key_part= (KEY_PART *) alloc_root(param->mem_root,
sizeof(KEY_PART) * parts)))
return TRUE;
@@ -3252,9 +3288,6 @@ bool create_key_parts_for_pseudo_indexes(RANGE_OPT_PARAM *param,
Field *field= *field_ptr;
if (bitmap_is_set(used_fields, field->field_index))
{
if (!is_eits_usable(field))
continue;
uint16 store_length;
uint16 max_key_part_length= (uint16) table->file->max_key_part_length();
key_part->key= keys;
@@ -3656,8 +3689,6 @@ end_of_range_loop:
PARAM param;
MEM_ROOT alloc;
SEL_TREE *tree;
double rows;
init_sql_alloc(key_memory_quick_range_select_root, &alloc,
thd->variables.range_alloc_block_size, 0,
MYF(MY_THREAD_SPECIFIC));
@@ -3668,68 +3699,93 @@ end_of_range_loop:
param.table= table;
param.remove_false_where_parts= true;
if (create_key_parts_for_pseudo_indexes(&param, used_fields))
goto free_alloc;
param.prev_tables= param.read_tables= 0;
param.current_table= table->map;
param.using_real_indexes= FALSE;
param.real_keynr[0]= 0;
MEM_UNDEFINED(&param.real_keynr, sizeof(param.real_keynr));
param.alloced_sel_args= 0;
param.max_key_parts= 0;
thd->no_errors=1;
if (!(tree= cond[0]->get_mm_tree(&param, cond)))
goto free_alloc;
thd->no_errors=1;
table->reginfo.impossible_range= 0;
if (tree->type == SEL_TREE::IMPOSSIBLE)
{
rows= 0;
table->reginfo.impossible_range= 1;
goto free_alloc;
}
else if (tree->type == SEL_TREE::ALWAYS)
{
rows= table_records;
goto free_alloc;
}
else if (tree->type == SEL_TREE::MAYBE)
{
rows= table_records;
goto free_alloc;
}
for (uint idx= 0; idx < param.keys; idx++)
uint used_fields_buff_size= bitmap_buffer_size(table->s->fields);
my_bitmap_map *used_fields_buff= (my_bitmap_map*)thd->alloc(used_fields_buff_size);
MY_BITMAP cols_for_indexes;
(void) my_bitmap_init(&cols_for_indexes, used_fields_buff, table->s->fields);
bitmap_clear_all(&cols_for_indexes);
uint column_no= 0; // Start looping from the first column.
/*
Try getting selectivity estimates for every field that is used in the
query and has EITS statistics. We do this:
for every usable field col
create a pseudo INDEX(col);
Run the range analyzer (get_mm_tree) for these pseudo-indexes;
Look at produced ranges and get their selectivity estimates;
Note that the range analyzer can process at most MAX_KEY indexes. If
the table has >MAX_KEY eligible columns, we will do several range
analyzer runs.
*/
while (1)
{
SEL_ARG *key= tree->keys[idx];
if (key) // Quick range found for key
column_no= get_columns_for_pseudo_indexes(table, used_fields, column_no,
&cols_for_indexes);
if (column_no == (uint)-1)
break; /* Couldn't create any pseudo-indexes. This means we're done */
if (create_key_parts_for_pseudo_indexes(&param, &cols_for_indexes))
goto free_alloc;
tree= cond[0]->get_mm_tree(&param, cond);
if (!tree ||
tree->type == SEL_TREE::ALWAYS ||
tree->type == SEL_TREE::MAYBE)
{
Json_writer_object selectivity_for_column(thd);
selectivity_for_column.add("column_name", key->field->field_name);
if (key->type == SEL_ARG::IMPOSSIBLE)
/* Couldn't infer anything. But there could be more fields, so continue */
continue;
}
if (tree->type == SEL_TREE::IMPOSSIBLE)
{
table->reginfo.impossible_range= 1;
goto free_alloc;
}
for (uint idx= 0; idx < param.keys; idx++)
{
SEL_ARG *key= tree->keys[idx];
if (key)
{
rows= 0;
table->reginfo.impossible_range= 1;
if (unlikely(selectivity_for_column.trace_started()))
selectivity_for_column.
add("selectivity_from_histogram", rows).
add("cause", "impossible range");
goto free_alloc;
}
else
{
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
rows= records_in_column_ranges(&param, idx, key);
thd->count_cuted_fields= save_count_cuted_fields;
if (rows != DBL_MAX)
Json_writer_object selectivity_for_column(thd);
selectivity_for_column.add("column_name", key->field->field_name);
if (key->type == SEL_ARG::IMPOSSIBLE)
{
key->field->cond_selectivity= rows/table_records;
DBUG_ASSERT(key->field->cond_selectivity <= 1.0);
selectivity_for_column.add("selectivity_from_histogram",
key->field->cond_selectivity);
table->reginfo.impossible_range= 1;
if (unlikely(selectivity_for_column.trace_started()))
selectivity_for_column.
add("selectivity_from_histogram", 0).
add("cause", "impossible range");
goto free_alloc;
}
else
{
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
double rows= records_in_column_ranges(&param, idx, key);
thd->count_cuted_fields= save_count_cuted_fields;
if (rows != DBL_MAX)
{
key->field->cond_selectivity= rows/table_records;
selectivity_for_column.add("selectivity_from_histogram",
key->field->cond_selectivity);
}
}
}
}
@@ -6964,8 +7020,7 @@ ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param)
void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
{
dst->param= src->param;
memcpy(dst->covered_fields.bitmap, src->covered_fields.bitmap,
no_bytes_in_map(&src->covered_fields));
bitmap_copy(&dst->covered_fields, &src->covered_fields);
dst->out_rows= src->out_rows;
dst->is_covering= src->is_covering;
dst->index_records= src->index_records;
@@ -7650,7 +7705,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
(*scan)->used_fields_covered=
bitmap_bits_set(&(*scan)->covered_fields);
(*scan)->first_uncovered_field=
bitmap_get_first(&(*scan)->covered_fields);
bitmap_get_first_clear(&(*scan)->covered_fields);
}
my_qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*),