1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

MDEV-30218: Incorrect optimization for rowid_filtering, correction

Enable use of Rowid Filter optimization with eq_ref access.
Use the following assumptions:
- Assume index-only access cost is 50% of non-index-only access cost.
- Take into account that "Eq_ref access cache" reduces the number of
  lookups eq_ref access will make.
  = This means the number of Rowid Filter checks is reduced also
  = Eq_ref access cost is computed using that assumption (see
    prev_record_reads() call), so we should use it in all cost '
    computations.
This commit is contained in:
Sergei Petrunia
2023-01-26 12:04:28 +03:00
committed by Oleksandr Byelkin
parent a977054ee0
commit 9c6fcdb85e
3 changed files with 73 additions and 15 deletions

View File

@ -7902,7 +7902,27 @@ best_access_path(JOIN *join,
(s->table->file->index_flags(start_key->key,0,1) &
HA_DO_RANGE_FILTER_PUSHDOWN))
{
double rows= record_count * records;
double rows;
if (type == JT_EQ_REF)
{
/*
Treat EQ_REF access in a special way:
1. We have no cost for index-only read. Assume its cost is 50% of
the cost of the full read.
2. A regular ref access will do #record_count lookups, but eq_ref
has "lookup cache" which reduces the number of lookups made.
The estimation code uses prev_record_reads() call to estimate:
tmp = prev_record_reads(join_positions, idx, found_ref);
Set the effective number of rows from "tmp" here.
*/
keyread_tmp= tmp/ 2;
rows= tmp;
}
else
rows= record_count * records;
/*
If we use filter F with selectivity s the the cost of fetching data
@ -7945,10 +7965,6 @@ best_access_path(JOIN *join,
we cannot use filters as the cost calculation below would cause
tmp to become negative. The future resultion is to not limit
cost with worst_seek.
We cannot use filter with JT_EQ_REF as in this case 'tmp' is
number of rows from prev_record_read() and keyread_tmp is 0. These
numbers are not usable with rowid filter code.
*/
double access_cost_factor= MY_MIN((rows - keyread_tmp) / rows, 1.0);
if (!(records < s->worst_seeks &&
@ -7956,7 +7972,7 @@ best_access_path(JOIN *join,
trace_access_idx.add("rowid_filter_skipped", "worst/max seeks clipping");
else if (access_cost_factor <= 0.0)
trace_access_idx.add("rowid_filter_skipped", "cost_factor <= 0");
else if (type != JT_EQ_REF)
else
{
filter=
table->best_range_rowid_filter_for_partial_join(start_key->key,