Commit fdb77fd3 authored by Varun Gupta's avatar Varun Gupta

Fix to address performance regression of ORDER BY with limit queries

parent 5a9e6261
......@@ -3140,7 +3140,7 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
best_access_path(join, join->positions[i].table, rem_tables,
join->positions, i,
disable_jbuf, prefix_rec_count, &curpos, &dummy,
0, FALSE);
0, FALSE, DBL_MAX);
prefix_rec_count= COST_MULT(prefix_rec_count, curpos.records_read);
prefix_cost= COST_ADD(prefix_cost, curpos.read_time);
prefix_cost= COST_ADD(prefix_cost,
......@@ -3839,7 +3839,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
best_access_path(join, join->best_positions[i].table, rem_tables,
join->best_positions, i,
FALSE, prefix_rec_count,
join->best_positions + i, &dummy, 0, FALSE);
join->best_positions + i, &dummy, 0, FALSE, DBL_MAX);
join->best_positions[i].sort_nest_operation_here= save_sort_nest_op;
prefix_rec_count *= join->best_positions[i].records_read;
rem_tables &= ~join->best_positions[i].table->table->map;
......@@ -3882,7 +3882,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
rem_tables, join->best_positions, idx,
TRUE /* no jbuf */,
record_count, join->best_positions + idx, &dummy,
0, FALSE);
0, FALSE, DBL_MAX);
}
record_count *= join->best_positions[idx].records_read;
rem_tables &= ~join->best_positions[idx].table->table->map;
......@@ -3922,7 +3922,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
rem_tables, join->best_positions, idx,
TRUE /* no jbuf */,
record_count, join->best_positions + idx,
&loose_scan_pos, 0, FALSE);
&loose_scan_pos, 0, FALSE, DBL_MAX);
if (idx==first)
{
join->best_positions[idx]= loose_scan_pos;
......
......@@ -119,7 +119,8 @@ static bool best_extension_by_limited_search(JOIN *join,
uint use_cond_selectivity,
table_map sort_nest_tables,
bool nest_created,
bool limit_applied_to_nest);
bool limit_applied_to_nest,
double sort_nest_records);
static uint determine_search_depth(JOIN* join);
C_MODE_START
static int join_tab_cmp(const void *dummy, const void* ptr1, const void* ptr2);
......@@ -7294,7 +7295,8 @@ best_access_path(JOIN *join,
double record_count,
POSITION *pos,
POSITION *loose_scan_pos,
table_map sort_nest_tables, bool nest_created)
table_map sort_nest_tables, bool nest_created,
double sort_nest_records)
{
THD *thd= join->thd;
uint use_cond_selectivity= thd->variables.optimizer_use_condition_selectivity;
......@@ -7415,9 +7417,9 @@ best_access_path(JOIN *join,
double tmp2= prev_record_reads(join_positions, idx,
(found_ref | keyuse->used_tables),
sort_nest_tables,
nest_created ?
join->fraction_output_for_nest :
1.0);
nest_created,
nest_created ? sort_nest_records:
DBL_MAX);
if (tmp2 < best_prev_record_reads)
{
best_part_found_ref= keyuse->used_tables & ~join->const_table_map;
......@@ -7459,9 +7461,8 @@ best_access_path(JOIN *join,
but 1.0 would be probably safer
*/
tmp= prev_record_reads(join_positions, idx, found_ref,
sort_nest_tables,
nest_created ?
join->fraction_output_for_nest : 1.0);
sort_nest_tables, nest_created,
nest_created ? sort_nest_records : DBL_MAX);
records= 1.0;
type= JT_FT;
trace_access_idx.add("access_type", join_type_str[type])
......@@ -7491,9 +7492,9 @@ best_access_path(JOIN *join,
trace_access_idx.add("access_type", join_type_str[type])
.add("index", keyinfo->name);
tmp = prev_record_reads(join_positions, idx, found_ref,
sort_nest_tables,
sort_nest_tables, nest_created,
nest_created ?
join->fraction_output_for_nest : 1.0);
sort_nest_records : DBL_MAX);
records=1.0;
}
else
......@@ -8147,7 +8148,6 @@ best_access_path(JOIN *join,
join->sort_by_table= (TABLE*) 1; // Must use temporary table
}
trace_access_scan.end();
trace_paths.end();
/*
Use the estimate of rows read for a table for range/table scan
......@@ -8222,6 +8222,8 @@ best_access_path(JOIN *join,
if (unlikely(thd->trace_started()))
print_best_access_for_table(thd, pos, best_type);
trace_paths.end();
DBUG_VOID_RETURN;
}
......@@ -8717,7 +8719,7 @@ optimize_straight_join(JOIN *join, table_map join_tables)
best_access_path(join, s, join_tables, join->positions, idx,
disable_jbuf, record_count,
position, &loose_scan_pos,
0, FALSE);
0, FALSE, DBL_MAX);
/* compute the cost of the new plan extended with 's' */
record_count= COST_MULT(record_count, position->records_read);
......@@ -8873,7 +8875,7 @@ greedy_search(JOIN *join,
prune_level),
use_cond_selectivity,
sort_nest_tables, FALSE,
FALSE))
FALSE, DBL_MAX))
DBUG_RETURN(TRUE);
/*
'best_read < DBL_MAX' means that optimizer managed to find
......@@ -9619,7 +9621,8 @@ best_extension_by_limited_search(JOIN *join,
uint use_cond_selectivity,
table_map sort_nest_tables,
bool nest_created,
bool limit_applied_to_nest)
bool limit_applied_to_nest,
double sort_nest_records)
{
DBUG_ENTER("best_extension_by_limited_search");
......@@ -9652,6 +9655,7 @@ best_extension_by_limited_search(JOIN *join,
double original_record_count= record_count;
record_count= COST_MULT(record_count, join->fraction_output_for_nest);
limit_applied_to_nest= TRUE;
sort_nest_records= record_count;
if (unlikely(thd->trace_started()))
{
......@@ -9706,7 +9710,7 @@ best_extension_by_limited_search(JOIN *join,
POSITION loose_scan_pos;
best_access_path(join, s, remaining_tables, join->positions, idx,
disable_jbuf, record_count, position, &loose_scan_pos,
sort_nest_tables, nest_created);
sort_nest_tables, nest_created, sort_nest_records);
/*
sort_nest_operation_here is set to TRUE here in the special case
......@@ -9810,7 +9814,10 @@ best_extension_by_limited_search(JOIN *join,
if (join->is_index_with_ordering_allowed(idx) &&
s->check_if_index_satisfies_ordering(index_used))
{
limit_applied_to_nest= TRUE;
sort_nest_records= partial_join_cardinality;
}
if (!nest_created &&
(join->prefix_resolves_ordering ||
......@@ -9839,7 +9846,8 @@ best_extension_by_limited_search(JOIN *join,
prune_level,
use_cond_selectivity,
sort_nest_tables | real_table_bit,
TRUE, limit_applied_to_nest))
TRUE, limit_applied_to_nest,
sort_nest_records))
DBUG_RETURN(TRUE);
if (!(join->is_index_with_ordering_allowed(idx) &&
s->check_if_index_satisfies_ordering(index_used)))
......@@ -9857,8 +9865,9 @@ best_extension_by_limited_search(JOIN *join,
use_cond_selectivity,
nest_created ? sort_nest_tables :
sort_nest_tables | real_table_bit,
nest_created,
limit_applied_to_nest))
nest_created || limit_applied_to_nest,
limit_applied_to_nest,
sort_nest_records))
DBUG_RETURN(TRUE);
trace_rest.end();
......@@ -9866,6 +9875,7 @@ best_extension_by_limited_search(JOIN *join,
{
limit_applied_to_nest= FALSE;
join->positions[idx].sort_nest_operation_here= FALSE;
sort_nest_records= DBL_MAX;
}
swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
}
......@@ -10236,8 +10246,8 @@ cache_record_length_for_nest(JOIN *join,uint idx)
double
prev_record_reads(const POSITION *positions, uint idx, table_map found_ref,
table_map sort_nest_tables,
double fraction_output_for_nest)
table_map sort_nest_tables, bool nest_created,
double sort_nest_records)
{
double found=1.0;
const POSITION *pos_end= positions - 1;
......@@ -10247,8 +10257,11 @@ prev_record_reads(const POSITION *positions, uint idx, table_map found_ref,
if (pos->table->table->map & found_ref)
{
found_ref|= pos->ref_depend_map;
if (pos->table->table->map & sort_nest_tables)
if (nest_created && pos->table->table->map & sort_nest_tables)
{
apply_limit= TRUE;
break;
}
/*
For the case of "t1 LEFT JOIN t2 ON ..." where t2 is a const table
with no matching row we will get position[t2].records_read==0.
......@@ -10272,8 +10285,15 @@ prev_record_reads(const POSITION *positions, uint idx, table_map found_ref,
}
}
}
/*
This needs to be done only once if the nest is created because we
would be referring to the context post sorting.
*/
if (apply_limit)
found= COST_MULT(found, fraction_output_for_nest);
{
DBUG_ASSERT(sort_nest_records != DBL_MAX);
found= COST_MULT(found, sort_nest_records);
}
return found;
}
......@@ -17351,7 +17371,7 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
join->positions, i,
TRUE, rec_count,
&pos, &loose_scan_pos,
0, FALSE);
0, FALSE, DBL_MAX);
}
else
pos= join->positions[i];
......
......@@ -881,7 +881,7 @@ class LooseScan_picker : public Semi_join_strategy_picker
struct st_position *pos,
struct st_position *loose_scan_pos,
table_map sort_nest_tables,
bool nest_created);
bool nest_created, double sort_nest_records);
friend bool get_best_combination(JOIN *join);
friend int setup_semijoin_loosescan(JOIN *join);
friend void fix_semijoin_strategies_for_picked_join_order(JOIN *join);
......@@ -2291,7 +2291,8 @@ void best_access_path(JOIN *join, JOIN_TAB *s,
const POSITION *join_positions, uint idx,
bool disable_jbuf, double record_count,
POSITION *pos, POSITION *loose_scan_pos,
table_map sort_nest_tables, bool nest_created);
table_map sort_nest_tables, bool nest_created,
double sort_nest_records);
bool cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref);
bool error_if_full_join(JOIN *join);
int report_error(TABLE *table, int error);
......@@ -2672,7 +2673,7 @@ bool open_tmp_table(TABLE *table);
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps);
double prev_record_reads(const POSITION *positions, uint idx, table_map found_ref,
table_map sort_nest_tables,
double fraction_output_for_nest);
bool nest_created, double sort_nest_records);
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist);
double get_tmp_table_lookup_cost(THD *thd, double row_count, ulong row_size);
......
......@@ -1039,7 +1039,7 @@ int get_best_index_for_order_by_limit(JOIN_TAB *tab,
double save_read_time= *read_time;
double save_records= *records;
double est_records= *records;
double fanout= MY_MAX(1.0, cardinality / est_records);
double fanout= cardinality / est_records;
int best_index=-1;
trace_index_for_ordering.add("rows_estimation", est_records);
Json_writer_array considered_indexes(thd, "considered_indexes");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment