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.cc55
1 files changed, 33 insertions, 22 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index d537dccc5a6..53c41482a36 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1898,7 +1898,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
best=best_time=records=DBL_MAX;
KEYUSE *best_key=0;
uint best_max_key_part=0;
- my_bool found_constrain= 0;
+ my_bool found_constraint= 0;
if (s->keyuse)
{ /* Use key if possible */
@@ -1979,7 +1979,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
}
else
{
- found_constrain= 1;
+ found_constraint= 1;
/*
Check if we found full key
*/
@@ -2133,12 +2133,28 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
s->table->used_keys && best_key) &&
!(s->table->force_index && best_key))
{ // Check full join
+ ha_rows rnd_records= s->found_records;
/* Estimate cost of reading table. */
- tmp= (double) s->read_time;
+ tmp= s->table->file->scan_time();
+ /*
+ If there is a restriction on the table, assume that 25% of the
+ rows can be skipped on next part.
+ This is to force tables that this table depends on before this
+ table
+ */
+ if (found_constraint)
+ rnd_records-= rnd_records/4;
+
if (s->on_expr) // Can't use join cache
{
- /* We have to read the whole table for each record */
- tmp*= record_count;
+ tmp= record_count *
+ /* We have to read the whole table for each record */
+ (tmp +
+ /*
+ And we have to skip rows which does not satisfy join
+ condition for each record.
+ */
+ (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
}
else
{
@@ -2146,30 +2162,25 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
record_count /
(double) thd->variables.join_buff_size));
+ /*
+ We don't make full cartesian product between rows in the scanned
+ table and existing records because we skip all rows from the
+ scanned table, which does not satisfy join condition when
+ we read the table (see flush_cached_records for details). Here we
+ take into account cost to read and skip these records.
+ */
+ tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
}
/*
- We estimate the cost of making full cortesian product between
- rows in the scanned table and generated records as
- record_count*s->records/TIME_FOR_COMPARE. Taking into account
- cost of evaluating WHERE clause for s->found_records is not
- necessary because it costs much less than the cost mentioned
- above.
+ We estimate the cost of evaluating WHERE clause for found records
+ as record_count * rnd_records + TIME_FOR_COMPARE. This cost plus
+ tmp give us total cost of using TABLE SCAN
*/
if (best == DBL_MAX ||
- (tmp + record_count/(double) TIME_FOR_COMPARE*s->records <
+ (tmp + record_count/(double) TIME_FOR_COMPARE*rnd_records <
best + record_count/(double) TIME_FOR_COMPARE*records))
{
- /*
- If there is a restriction on the table, assume that 25% of the
- rows can be skipped on next part.
- This is to force tables that this table depends on before this
- table
- */
- ha_rows rnd_records= s->found_records;
- if (found_constrain)
- rnd_records-= rnd_records/4;
-
/*
If the table has a range (s->quick is set) make_join_select()
will ensure that this will be used