Skip to content

Commit 7d10c12

Browse files
committed
bug#18558561: Replace Cost_estimate with a double when estimating join cost
The member variable prefix_cost of class POSITION is made a double. Since partial plans and complete plans are compared with a cost represented as a double, it makes sense to store this as a double too. The member variable prefix_record_count of class POSITION is renamed to prefix_rowcount for more consistent naming. The function set_prefix_costs() is renamed to set_prefix_cost(). A new function set_prefix_join_cost() that calculates the cost of a prefix plan has been added. The above change of type has made it possible to eliminate the arguments record_count and read_time that were currently shipped to some functions of class Optimize_table_order: consider_plan(), best_extension_by_limited_search(), eq_ref_extension_by_limited_search() and advance_sj_state(). These functions use member variables from POSITION instead. A new const property has_sj has been added to class Optimize_table_order, so it does not have to be calculated more than once. In JOIN::setup_materialized_table(), the cost of a semi-join materialization is correctly calculated, to keep a correct cost for a final plan.
1 parent a432ac7 commit 7d10c12

File tree

9 files changed

+259
-281
lines changed

9 files changed

+259
-281
lines changed

mysql-test/r/myisam_explain_json_non_select_all.result

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6399,14 +6399,14 @@ EXPLAIN
63996399
"table_name": "t2",
64006400
"access_type": "system",
64016401
"rows_examined_per_scan": 0,
6402-
"rows_produced_per_join": 0,
6402+
"rows_produced_per_join": 1,
64036403
"filtered": 0,
64046404
"const_row_not_found": true,
64056405
"cost_info": {
64066406
"read_cost": "0.00",
6407-
"eval_cost": "0.00",
6407+
"eval_cost": "0.20",
64086408
"prefix_cost": "0.00",
6409-
"data_read_per_join": "0"
6409+
"data_read_per_join": "16"
64106410
} /* cost_info */,
64116411
"used_columns": [
64126412
"c1",
@@ -6462,14 +6462,14 @@ EXPLAIN
64626462
"table_name": "t2",
64636463
"access_type": "system",
64646464
"rows_examined_per_scan": 0,
6465-
"rows_produced_per_join": 0,
6465+
"rows_produced_per_join": 1,
64666466
"filtered": 0,
64676467
"const_row_not_found": true,
64686468
"cost_info": {
64696469
"read_cost": "0.00",
6470-
"eval_cost": "0.00",
6470+
"eval_cost": "0.20",
64716471
"prefix_cost": "0.00",
6472-
"data_read_per_join": "0"
6472+
"data_read_per_join": "16"
64736473
} /* cost_info */,
64746474
"used_columns": [
64756475
"c1",
@@ -6546,14 +6546,14 @@ EXPLAIN
65466546
"table_name": "t2",
65476547
"access_type": "system",
65486548
"rows_examined_per_scan": 0,
6549-
"rows_produced_per_join": 0,
6549+
"rows_produced_per_join": 1,
65506550
"filtered": 0,
65516551
"const_row_not_found": true,
65526552
"cost_info": {
65536553
"read_cost": "0.00",
6554-
"eval_cost": "0.00",
6554+
"eval_cost": "0.20",
65556555
"prefix_cost": "0.00",
6556-
"data_read_per_join": "0"
6556+
"data_read_per_join": "16"
65576557
} /* cost_info */,
65586558
"used_columns": [
65596559
"c1",
@@ -6611,14 +6611,14 @@ EXPLAIN
66116611
"table_name": "t2",
66126612
"access_type": "system",
66136613
"rows_examined_per_scan": 0,
6614-
"rows_produced_per_join": 0,
6614+
"rows_produced_per_join": 1,
66156615
"filtered": 0,
66166616
"const_row_not_found": true,
66176617
"cost_info": {
66186618
"read_cost": "0.00",
6619-
"eval_cost": "0.00",
6619+
"eval_cost": "0.20",
66206620
"prefix_cost": "0.00",
6621-
"data_read_per_join": "0"
6621+
"data_read_per_join": "16"
66226622
} /* cost_info */,
66236623
"used_columns": [
66246624
"c1",

mysql-test/r/myisam_explain_json_non_select_none.result

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6430,14 +6430,14 @@ EXPLAIN
64306430
"table_name": "t2",
64316431
"access_type": "system",
64326432
"rows_examined_per_scan": 0,
6433-
"rows_produced_per_join": 0,
6433+
"rows_produced_per_join": 1,
64346434
"filtered": 0,
64356435
"const_row_not_found": true,
64366436
"cost_info": {
64376437
"read_cost": "0.00",
6438-
"eval_cost": "0.00",
6438+
"eval_cost": "0.20",
64396439
"prefix_cost": "0.00",
6440-
"data_read_per_join": "0"
6440+
"data_read_per_join": "16"
64416441
} /* cost_info */,
64426442
"used_columns": [
64436443
"c1",
@@ -6493,14 +6493,14 @@ EXPLAIN
64936493
"table_name": "t2",
64946494
"access_type": "system",
64956495
"rows_examined_per_scan": 0,
6496-
"rows_produced_per_join": 0,
6496+
"rows_produced_per_join": 1,
64976497
"filtered": 0,
64986498
"const_row_not_found": true,
64996499
"cost_info": {
65006500
"read_cost": "0.00",
6501-
"eval_cost": "0.00",
6501+
"eval_cost": "0.20",
65026502
"prefix_cost": "0.00",
6503-
"data_read_per_join": "0"
6503+
"data_read_per_join": "16"
65046504
} /* cost_info */,
65056505
"used_columns": [
65066506
"c1",
@@ -6577,14 +6577,14 @@ EXPLAIN
65776577
"table_name": "t2",
65786578
"access_type": "system",
65796579
"rows_examined_per_scan": 0,
6580-
"rows_produced_per_join": 0,
6580+
"rows_produced_per_join": 1,
65816581
"filtered": 0,
65826582
"const_row_not_found": true,
65836583
"cost_info": {
65846584
"read_cost": "0.00",
6585-
"eval_cost": "0.00",
6585+
"eval_cost": "0.20",
65866586
"prefix_cost": "0.00",
6587-
"data_read_per_join": "0"
6587+
"data_read_per_join": "16"
65886588
} /* cost_info */,
65896589
"used_columns": [
65906590
"c1",
@@ -6642,14 +6642,14 @@ EXPLAIN
66426642
"table_name": "t2",
66436643
"access_type": "system",
66446644
"rows_examined_per_scan": 0,
6645-
"rows_produced_per_join": 0,
6645+
"rows_produced_per_join": 1,
66466646
"filtered": 0,
66476647
"const_row_not_found": true,
66486648
"cost_info": {
66496649
"read_cost": "0.00",
6650-
"eval_cost": "0.00",
6650+
"eval_cost": "0.20",
66516651
"prefix_cost": "0.00",
6652-
"data_read_per_join": "0"
6652+
"data_read_per_join": "16"
66536653
} /* cost_info */,
66546654
"used_columns": [
66556655
"c1",

sql/opt_explain.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,14 +1486,14 @@ bool Explain_join::explain_rows_and_filtered()
14861486
fmt->entry()->col_filtered.set(filter);
14871487
}
14881488
// Print cost-related info
1489-
double prefix_rows= tab->position->prefix_record_count;
1489+
double prefix_rows= tab->position->prefix_rowcount;
14901490
fmt->entry()->col_prefix_rows.set(static_cast<ulonglong>(prefix_rows));
14911491
double const cond_cost= join->cost_model()->row_evaluate_cost(prefix_rows);
14921492
fmt->entry()->col_cond_cost.set(cond_cost < 0 ? 0 : cond_cost);
14931493

14941494
fmt->entry()->col_read_cost.set(tab->position->read_cost < 0.0 ?
14951495
0.0 : tab->position->read_cost);
1496-
fmt->entry()->col_prefix_cost.set(tab->position->prefix_cost.get_io_cost());
1496+
fmt->entry()->col_prefix_cost.set(tab->position->prefix_cost);
14971497

14981498
// Calculate amount of data from this table per query
14991499
char data_size_str[32];

sql/sql_executor.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,12 +1836,11 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos)
18361836
/* Mark for EXPLAIN that the row was not found */
18371837
pos->filter_effect= 1.0;
18381838
pos->rows_fetched= 0.0;
1839-
pos->prefix_record_count= 0.0;
1839+
pos->prefix_rowcount= 0.0;
18401840
pos->ref_depend_map= 0;
18411841
if (!table->pos_in_table_list->outer_join || error > 0)
18421842
DBUG_RETURN(error);
18431843
}
1844-
18451844

18461845
if (tab->join_cond() && !table->null_row)
18471846
{

sql/sql_optimizer.cc

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7589,7 +7589,7 @@ void JOIN::mark_const_table(JOIN_TAB *tab, Key_use *key)
75897589
position->key= key;
75907590
position->rows_fetched= 1.0; // This is a const table
75917591
position->filter_effect= 1.0;
7592-
position->prefix_record_count= 1.0;
7592+
position->prefix_rowcount= 1.0;
75937593
position->read_cost= 0.0;
75947594
position->ref_depend_map= 0;
75957595
position->loosescan_key= MAX_KEY; // Not a LooseScan
@@ -10162,10 +10162,8 @@ static void calculate_materialization_costs(JOIN *join,
1016210162
get_partial_join_cost() assumes a regular join, which is correct when
1016310163
we optimize a sj-materialization nest (always executed as regular
1016410164
join).
10165-
@todo consider using join->best_rowcount instead.
1016610165
*/
10167-
get_partial_join_cost(join, n_tables,
10168-
&mat_cost, &mat_rowcount);
10166+
get_partial_join_cost(join, n_tables, &mat_cost, &mat_rowcount);
1016910167
n_tables+= join->const_tables;
1017010168
inner_expr_list= &sj_nest->nested_join->sj_inner_exprs;
1017110169
}
@@ -10415,25 +10413,25 @@ bool JOIN::compare_costs_of_subquery_strategies(
1041510413
if (subs->in_cond_of_tab != INT_MIN)
1041610414
{
1041710415
/*
10418-
Subquery is attached to a certain 'pos', pos[-1].prefix_record_count
10416+
Subquery is attached to a certain 'pos', pos[-1].prefix_rowcount
1041910417
is the number of times we'll start a loop accessing 'pos'; each such
10420-
loop will read pos->rows_fetched records of 'pos', so subquery will
10421-
be evaluated pos[-1].prefix_record_count * pos->rows_fetched times.
10418+
loop will read pos->rows_fetched rows of 'pos', so subquery will
10419+
be evaluated pos[-1].prefix_rowcount * pos->rows_fetched times.
1042210420
Exceptions:
10423-
- if 'pos' is first, use 1 instead of pos[-1].prefix_record_count
10421+
- if 'pos' is first, use 1.0 instead of pos[-1].prefix_rowcount
1042410422
- if 'pos' is first of a sj-materialization nest, same.
1042510423
1042610424
If in a sj-materialization nest, pos->rows_fetched and
10427-
pos[-1].prefix_record_count are of the "nest materialization" plan
10425+
pos[-1].prefix_rowcount are of the "nest materialization" plan
1042810426
(copied back in fix_semijoin_strategies()), which is
1042910427
appropriate as it corresponds to evaluations of our subquery.
1043010428
10431-
pos.prefix_record_count is not suitable because if we have:
10429+
pos->prefix_rowcount is not suitable because if we have:
1043210430
select ... from ot1 where ot1.col in
1043310431
(select it1.col1 from it1 where it1.col2 not in (subq));
1043410432
and subq does subq-mat, and plan is ot1 - it1+firstmatch(ot1),
1043510433
then:
10436-
- t1.prefix_record_count==1 (due to firstmatch)
10434+
- t1.prefix_rowcount==1 (due to firstmatch)
1043710435
- subq is attached to it1, and is evaluated for each row read from
1043810436
t1, potentially way more than 1.
1043910437
*/
@@ -10446,7 +10444,7 @@ bool JOIN::compare_costs_of_subquery_strategies(
1044610444
!sj_is_materialize_strategy(parent_join
1044710445
->join_tab[idx].position->sj_strategy))
1044810446
parent_fanout*=
10449-
parent_join->join_tab[idx - 1].position->prefix_record_count;
10447+
parent_join->join_tab[idx - 1].position->prefix_rowcount;
1045010448
}
1045110449
else
1045210450
{

0 commit comments

Comments
 (0)