Skip to content

Commit 9849e3f

Browse files
committed
MDEV-35072: Assertion with optimizer_join_limit_pref_ratio and 1-table select
Pre-11.0 variant: 1. In recompute_join_cost_with_limit(), add an assertion that that partial_join_cost >= 0.0. 2. best_extension_by_limited_search() subtracts COST_EPS from join->best_read. But it is not subtracted from join->positions[0].read_time, add it back. 2. We could get very small negative partial_join_cost due to rounding errors. For fraction=1.0, we were computing essentially this (denote as EXPR-1): $row_read_cost + $where_cost - ($row_read_cost + $where_cost) which should compute to 0. But the computation was done in the following order (left-to-right): EXPR-2: ($row_read_cost + $where_cost) - $row_read_cost - $where_cost this produced a value of -1.1102230246251565e-16 due to a rounding error. Change the computation use EXPR-1 instead of EXPR-2.
1 parent 5619f29 commit 9849e3f

File tree

3 files changed

+44
-10
lines changed

3 files changed

+44
-10
lines changed

mysql-test/main/order_by_limit_join.result

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ JS
111111
"full_join_cost": "REPLACED",
112112
"risk_ratio": 10,
113113
"shortcut_join_cost": "REPLACED",
114-
"shortcut_cost_with_risk": 972.8224614,
114+
"shortcut_cost_with_risk": 972.8224714,
115115
"use_shortcut_cost": true
116116
}
117117
]
@@ -163,7 +163,7 @@ JS
163163
"full_join_cost": "REPLACED",
164164
"risk_ratio": 10,
165165
"shortcut_join_cost": "REPLACED",
166-
"shortcut_cost_with_risk": 20972.81246,
166+
"shortcut_cost_with_risk": 20972.81247,
167167
"use_shortcut_cost": true
168168
}
169169
]
@@ -247,7 +247,7 @@ JS
247247
"full_join_cost": "REPLACED",
248248
"risk_ratio": 10,
249249
"shortcut_join_cost": "REPLACED",
250-
"shortcut_cost_with_risk": 240591.2698,
250+
"shortcut_cost_with_risk": 240591.2748,
251251
"use_shortcut_cost": false
252252
}
253253
]
@@ -366,7 +366,7 @@ JS
366366
"full_join_cost": "REPLACED",
367367
"risk_ratio": 10,
368368
"shortcut_join_cost": "REPLACED",
369-
"shortcut_cost_with_risk": 982.9697856,
369+
"shortcut_cost_with_risk": 982.9697956,
370370
"use_shortcut_cost": true
371371
}
372372
]
@@ -451,11 +451,21 @@ JS
451451
"full_join_cost": "REPLACED",
452452
"risk_ratio": 10,
453453
"shortcut_join_cost": "REPLACED",
454-
"shortcut_cost_with_risk": 972.8224614,
454+
"shortcut_cost_with_risk": 972.8224714,
455455
"use_shortcut_cost": true
456456
}
457457
]
458458
set optimizer_search_depth=@tmp_osd;
459459
set optimizer_trace=@tmp_os;
460-
set optimizer_join_limit_pref_ratio=default;
461460
drop table t1, t10, t11;
461+
#
462+
# MDEV-35072: Assertion failure with optimizer_join_limit_pref_ratio and 1-table select
463+
#
464+
SET optimizer_join_limit_pref_ratio=1;
465+
CREATE TABLE t1 (c1 INT, INDEX(c1));
466+
INSERT INTO t1 VALUES (1),(2);
467+
SELECT * FROM t1 ORDER BY c1 LIMIT 1;
468+
c1
469+
1
470+
DROP TABLE t1;
471+
set optimizer_join_limit_pref_ratio=default;

mysql-test/main/order_by_limit_join.test

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,15 @@ select json_detailed(json_extract(@trace, '$**.join_limit_shortcut_choice')) as
208208

209209
set optimizer_search_depth=@tmp_osd;
210210
set optimizer_trace=@tmp_os;
211-
set optimizer_join_limit_pref_ratio=default;
212211
drop table t1, t10, t11;
213212

213+
--echo #
214+
--echo # MDEV-35072: Assertion failure with optimizer_join_limit_pref_ratio and 1-table select
215+
--echo #
216+
SET optimizer_join_limit_pref_ratio=1;
217+
CREATE TABLE t1 (c1 INT, INDEX(c1));
218+
INSERT INTO t1 VALUES (1),(2);
219+
SELECT * FROM t1 ORDER BY c1 LIMIT 1;
220+
DROP TABLE t1;
221+
222+
set optimizer_join_limit_pref_ratio=default;

sql/sql_select.cc

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10616,8 +10616,11 @@ double recompute_join_cost_with_limit(const JOIN *join, bool skip_sorting,
1061610616
POSITION *pos= join->best_positions + join->const_tables;
1061710617
/*
1061810618
Generally, we assume that producing X% of output takes X% of the cost.
10619+
10620+
best_extension_by_limited_search() subtracts COST_EPS from
10621+
join->best_read, add it back.
1061910622
*/
10620-
double partial_join_cost= join->best_read * fraction;
10623+
double partial_join_cost= (join->best_read + COST_EPS) * fraction;
1062110624

1062210625
if (skip_sorting)
1062310626
{
@@ -10634,12 +10637,20 @@ double recompute_join_cost_with_limit(const JOIN *join, bool skip_sorting,
1063410637
*/
1063510638
if (first_table_cost)
1063610639
{
10640+
/*
10641+
Compute the cost of accessing the first table in the same way as
10642+
it was done in greedy_search():
10643+
*/
10644+
double prev_first_table_cost;
10645+
prev_first_table_cost= pos->read_time +
10646+
(double)pos->records_read / TIME_FOR_COMPARE;
10647+
prev_first_table_cost *= fraction;
1063710648
/*
1063810649
Subtract the remainder of the first table's cost we had in
1063910650
join->best_read:
1064010651
*/
10641-
partial_join_cost -= pos->read_time*fraction;
10642-
partial_join_cost -= pos->records_read*fraction / TIME_FOR_COMPARE;
10652+
partial_join_cost -= prev_first_table_cost;
10653+
DBUG_ASSERT(partial_join_cost >= 0.0);
1064310654

1064410655
/* Add the cost of the new access method we've got: */
1064510656
partial_join_cost= COST_ADD(partial_join_cost, *first_table_cost);
@@ -11093,6 +11104,10 @@ best_extension_by_limited_search(JOIN *join,
1109311104
memcpy((uchar*) join->best_positions, (uchar*) join->positions,
1109411105
sizeof(POSITION) * (idx + 1));
1109511106
join->join_record_count= partial_join_cardinality;
11107+
/*
11108+
note: recompute_join_cost_with_limit() relies on this COST_EPS
11109+
subtraction:
11110+
*/
1109611111
join->best_read= current_read_time - COST_EPS;
1109711112
}
1109811113
DBUG_EXECUTE("opt", print_plan(join, idx+1,

0 commit comments

Comments
 (0)