summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc98
1 files changed, 38 insertions, 60 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f313d571b5b..6a441c5047b 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -7887,9 +7887,7 @@ best_access_path(JOIN *join,
} /* not ft_key */
if (records < DBL_MAX &&
- (found_part & 1) && // start_key->key can be used for index access
- (s->table->file->index_flags(start_key->key,0,1) &
- HA_DO_RANGE_FILTER_PUSHDOWN))
+ (found_part & 1)) // start_key->key can be used for index access
{
double rows= record_count * records;
@@ -7914,50 +7912,33 @@ best_access_path(JOIN *join,
cost_of_fetching_1_row = tmp/rows
cost_of_fetching_1_key_tuple = keyread_tmp/rows
- access_cost_factor is the gain we expect for using rowid filter.
- An access_cost_factor of 1.0 means that keyread_tmp is 0
- (using key read is infinitely fast) and the gain for each row when
- using filter is great.
- An access_cost_factor if 0.0 means that using keyread has the
- same cost as reading rows, so there is no gain to get with
- filter.
- access_cost_factor should never be bigger than 1.0 (if all
- calculations are correct) as the cost of keyread should always be
- smaller than the cost of fetching the same number of keys + rows.
- access_cost_factor should also never be smaller than 0.0.
- The one exception is if number of records is 1 (eq_ref), then
- because we are comparing rows to cost of keyread_tmp, keyread_tmp
- is higher by 1.0. This is a big that will be fixed in a later
- version.
-
- If we have limited the cost (=tmp) of reading rows with 'worst_seek'
- 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.
+ Currently the calculation of cost_of_fetching_1_row and
+ cost_of_fetching_1_key_tuple is done by functions that are
+ not quite correspond each other. Currently there are several
+ irregularities in the code. For example if we use values
+ of records_per_key from statistical tables and some engine
+ uses its own records_per_key to calculate the cost of fetching
+ records for one key then the value of keyread_tmp might happen
+ to be bigger than the value of tmp. We avoid this by capping
+ the value of keyread_tmp by the value tmp in the formula that
+ calculates possible gain of using a certain rowid filter.
+ We also have a special handling of the case when the joined
+ table is accessed by eq_ref access.
*/
- double access_cost_factor= MY_MIN((rows - keyread_tmp) / rows, 1.0);
- if (!(records < s->worst_seeks &&
- records <= thd->variables.max_seeks_for_key))
- 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)
+
+ double key_access_cost=
+ type == JT_EQ_REF ? 0.5 * tmp : MY_MIN(tmp, keyread_tmp);
+ double access_cost_factor= MY_MIN((tmp - key_access_cost) / rows, 1.0);
+ filter=
+ table->best_range_rowid_filter_for_partial_join(start_key->key,
+ rows,
+ access_cost_factor);
+ if (filter)
{
- filter=
- table->best_range_rowid_filter_for_partial_join(start_key->key,
- rows,
- access_cost_factor);
- if (filter)
- {
- tmp-= filter->get_adjusted_gain(rows) - filter->get_cmp_gain(rows);
- DBUG_ASSERT(tmp >= 0);
- trace_access_idx.add("rowid_filter_key",
- s->table->key_info[filter->key_no].name);
- }
+ tmp-= filter->get_adjusted_gain(rows) - filter->get_cmp_gain(rows);
+ DBUG_ASSERT(tmp >= 0);
+ trace_access_idx.add("rowid_filter_key",
+ s->table->key_info[filter->key_no].name);
}
}
trace_access_idx.add("rows", records).add("cost", tmp);
@@ -8110,23 +8091,20 @@ best_access_path(JOIN *join,
uint key_no= s->quick->index;
/* See the comment concerning using rowid filter for with ref access */
- keyread_tmp= s->table->quick_index_only_costs[key_no] * record_count;
- double access_cost_factor= MY_MIN((rows - keyread_tmp) / rows, 1.0);
- if (access_cost_factor > 0.0)
+ double row_access_cost= s->quick->read_time * record_count;
+ double key_access_cost=
+ MY_MIN(row_access_cost,
+ s->table->quick_index_only_costs[key_no] * record_count);
+ double access_cost_factor= MY_MIN((row_access_cost - key_access_cost) /
+ rows, 1.0);
+ filter=
+ s->table->best_range_rowid_filter_for_partial_join(key_no, rows,
+ access_cost_factor);
+ if (filter)
{
- filter=
- s->table->
- best_range_rowid_filter_for_partial_join(key_no, rows,
- access_cost_factor);
- if (filter)
- {
- tmp-= filter->get_adjusted_gain(rows);
- DBUG_ASSERT(tmp >= 0);
- }
+ tmp-= filter->get_adjusted_gain(rows);
+ DBUG_ASSERT(tmp >= 0);
}
- else
- trace_access_scan.add("rowid_filter_skipped", "cost_factor <= 0");
-
type= JT_RANGE;
}
else