Skip to content

Commit c4ce65c

Browse files
committed
BUG#20483278 LAST_QUERY_COST SHOWS DIFFERENT VALUES FOR SHOW_COMPATIBLITY
FOR ON VS OFF BUG#21788549 LAST_QUERY_PARTIAL_PLANS VALUES NOT SAME WITH SHOW_COMPATIBILITY_56 Before this fix, With SHOW_COMPATIBILITY_56=ON, The statement SHOW STATUS like 'Last_query_cost'; was executed with dedicated code in the information schema (sql/sql_show.cc), which is -- not -- implemented as a storage engine. As a result, this statement did not execute code in the optimizer, which did not overwrite the session status variable 'Last_query_cost' for the current select statement. As a result, the value of 'Last_query_cost' reported was for the previous SELECT statement executed in the session. With SHOW_COMPATIBILITY_56=OFF, SHOW STATUS like 'Last_query_cost'; is executed as a SELECT ... FROM performance_schema.session_status. This table is implemented with a storage engine, and the optimizer code is used. By the time the value is returned, the value of 'Last_query_cost' reported is the value just overwritten by the optimizer for the current statement, which is not the desired result. The fix is to separate clearly in the session attributes: - the value of 'Last_query_cost' for the current query, - the value of 'Last_query_cost' for the previous query, and only save the former in the later when query execution is complete. The same issue exists for Last_query_partial_plan, which is fixed the same way.
1 parent 624b12d commit c4ce65c

File tree

7 files changed

+120
-8
lines changed

7 files changed

+120
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
select @@global.show_compatibility_56 into @show_compatibility_56_save;
2+
================================================================================
3+
SHOW_COMPATIBILITY_56 = ON
4+
================================================================================
5+
set global show_compatibility_56 = on;
6+
select 1;
7+
1
8+
1
9+
SHOW STATUS LIKE 'Last_query_partial_plans';
10+
Variable_name Value
11+
Last_query_partial_plans 0
12+
select 2;
13+
2
14+
2
15+
SHOW STATUS LIKE 'Last_query_cost';
16+
Variable_name Value
17+
Last_query_cost 0.000000
18+
19+
================================================================================
20+
SHOW_COMPATIBILITY_56 = OFF
21+
================================================================================
22+
set global show_compatibility_56 = off;
23+
select 1;
24+
1
25+
1
26+
SHOW STATUS LIKE 'Last_query_partial_plans';
27+
Variable_name Value
28+
Last_query_partial_plans 0
29+
select 2;
30+
2
31+
2
32+
SHOW STATUS LIKE 'Last_query_cost';
33+
Variable_name Value
34+
Last_query_cost 0.000000
35+
36+
================================================================================
37+
CLEAN UP
38+
================================================================================
39+
set @@global.show_compatibility_56 = @show_compatibility_56_save;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--source include/have_perfschema.inc
2+
--source include/not_embedded.inc
3+
--source include/no_protocol.inc
4+
5+
select @@global.show_compatibility_56 into @show_compatibility_56_save;
6+
7+
--echo ================================================================================
8+
--echo SHOW_COMPATIBILITY_56 = ON
9+
--echo ================================================================================
10+
set global show_compatibility_56 = on;
11+
12+
select 1;
13+
SHOW STATUS LIKE 'Last_query_partial_plans';
14+
select 2;
15+
SHOW STATUS LIKE 'Last_query_cost';
16+
17+
18+
--echo
19+
--echo ================================================================================
20+
--echo SHOW_COMPATIBILITY_56 = OFF
21+
--echo ================================================================================
22+
set global show_compatibility_56 = off;
23+
24+
select 1;
25+
SHOW STATUS LIKE 'Last_query_partial_plans';
26+
select 2;
27+
SHOW STATUS LIKE 'Last_query_cost';
28+
29+
--echo
30+
--echo ================================================================================
31+
--echo CLEAN UP
32+
--echo ================================================================================
33+
set @@global.show_compatibility_56 = @show_compatibility_56_save;
34+

sql/sql_cache.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -1906,7 +1906,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
19061906
#endif /*!EMBEDDED_LIBRARY*/
19071907

19081908
thd->limit_found_rows = query->found_rows();
1909-
thd->status_var.last_query_cost= 0.0;
1909+
thd->clear_current_query_costs();
1910+
thd->save_current_query_costs();
19101911

19111912
{
19121913
Opt_trace_start ots(thd, NULL, SQLCOM_SELECT, NULL,

sql/sql_class.h

+37
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,43 @@ class THD :public MDL_context_owner,
15501550
struct system_status_var *initial_status_var; /* used by show status */
15511551
// has status_var already been added to global_status_var?
15521552
bool status_var_aggregated;
1553+
1554+
/**
1555+
Current query cost.
1556+
@sa system_status_var::last_query_cost
1557+
*/
1558+
double m_current_query_cost;
1559+
/**
1560+
Current query partial plans.
1561+
@sa system_status_var::last_query_partial_plans
1562+
*/
1563+
ulonglong m_current_query_partial_plans;
1564+
1565+
/**
1566+
Clear the query costs attributes for the current query.
1567+
*/
1568+
void clear_current_query_costs()
1569+
{
1570+
m_current_query_cost= 0.0;
1571+
m_current_query_partial_plans= 0;
1572+
}
1573+
1574+
/**
1575+
Save the current query costs attributes in
1576+
the thread session status.
1577+
Use this method only after the query execution is completed,
1578+
so that
1579+
@code SHOW SESSION STATUS like 'last_query_%' @endcode
1580+
@code SELECT * from performance_schema.session_status
1581+
WHERE VARIABLE_NAME like 'last_query_%' @endcode
1582+
actually reports the previous query, not itself.
1583+
*/
1584+
void save_current_query_costs()
1585+
{
1586+
status_var.last_query_cost= m_current_query_cost;
1587+
status_var.last_query_partial_plans= m_current_query_partial_plans;
1588+
}
1589+
15531590
THR_LOCK_INFO lock_info; // Locking info of this thread
15541591
/**
15551592
Protects THD data accessed from other threads.

sql/sql_optimizer.cc

+4-4
Original file line numberDiff line numberDiff line change
@@ -690,13 +690,13 @@ JOIN::optimize()
690690
DBUG_RETURN(1);
691691
}
692692

693-
// Update last_query_cost to reflect actual need of filesort.
693+
// Update m_current_query_cost to reflect actual need of filesort.
694694
if (sort_cost > 0.0 && !explain_flags.any(ESP_USING_FILESORT))
695695
{
696696
best_read-= sort_cost;
697697
sort_cost= 0.0;
698698
if (thd->lex->is_single_level_stmt())
699-
thd->status_var.last_query_cost= best_read;
699+
thd->m_current_query_cost= best_read;
700700
}
701701

702702
count_field_types(select_lex, &tmp_table_param, all_fields, false, false);
@@ -5030,12 +5030,12 @@ bool JOIN::make_join_plan()
50305030

50315031
/*
50325032
Store the cost of this query into a user variable
5033-
Don't update last_query_cost for statements that are not "flat joins" :
5033+
Don't update m_current_query_cost for statements that are not "flat joins" :
50345034
i.e. they have subqueries, unions or call stored procedures.
50355035
TODO: calculate a correct cost for a query with subqueries and UNIONs.
50365036
*/
50375037
if (thd->lex->is_single_level_stmt())
5038-
thd->status_var.last_query_cost= best_read;
5038+
thd->m_current_query_cost= best_read;
50395039

50405040
// Generate an execution plan from the found optimal join order.
50415041
if (get_best_combination())

sql/sql_parse.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -2589,14 +2589,15 @@ mysql_execute_command(THD *thd, bool first_level)
25892589
DBUG_EXECUTE_IF("use_attachable_trx",
25902590
thd->begin_attachable_transaction(););
25912591

2592-
thd->status_var.last_query_cost= 0.0;
2593-
thd->status_var.last_query_partial_plans= 0;
2592+
thd->clear_current_query_costs();
25942593

25952594
res= select_precheck(thd, lex, all_tables, first_table);
25962595

25972596
if (!res)
25982597
res= execute_sqlcom_select(thd, all_tables);
25992598

2599+
thd->save_current_query_costs();
2600+
26002601
DBUG_EXECUTE_IF("use_attachable_trx",
26012602
thd->end_attachable_transaction(););
26022603

sql/sql_planner.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ void Optimize_table_order::best_access_path(JOIN_TAB *tab,
914914

915915
float filter_effect= 1.0;
916916

917-
thd->status_var.last_query_partial_plans++;
917+
thd->m_current_query_partial_plans++;
918918

919919
/*
920920
Cannot use join buffering if either

0 commit comments

Comments
 (0)