mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Bug #30377: EXPLAIN loses last_query_cost when used with UNION
Currently the Last_query_cost session status variable shows only the cost of a single flat subselect. For complex queries (with subselects or unions etc) Last_query_cost is not valid as it was showing the cost for the last optimized subselect. Fixed by reseting to zero Last_query_cost when the complete cost of the query cannot be determined. Last_query_cost will be non-zero only for single flat queries.
This commit is contained in:
parent
4446fd4b0d
commit
cfaa0983c8
4 changed files with 108 additions and 2 deletions
|
@ -43,3 +43,51 @@ SHOW STATUS LIKE 'max_used_connections';
|
|||
Variable_name Value
|
||||
Max_used_connections 4
|
||||
SET GLOBAL thread_cache_size=@save_thread_cache_size;
|
||||
CREATE TABLE t1 ( a INT );
|
||||
INSERT INTO t1 VALUES (1), (2);
|
||||
SELECT a FROM t1 LIMIT 1;
|
||||
a
|
||||
1
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
Variable_name Value
|
||||
Last_query_cost 2.402418
|
||||
EXPLAIN SELECT a FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
Variable_name Value
|
||||
Last_query_cost 2.402418
|
||||
SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY a;
|
||||
a
|
||||
1
|
||||
2
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
Variable_name Value
|
||||
Last_query_cost 0.000000
|
||||
EXPLAIN SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
|
||||
2 UNION t1 ALL NULL NULL NULL NULL 2
|
||||
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL Using filesort
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
Variable_name Value
|
||||
Last_query_cost 0.000000
|
||||
SELECT a IN (SELECT a FROM t1) FROM t1 LIMIT 1;
|
||||
a IN (SELECT a FROM t1)
|
||||
1
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
Variable_name Value
|
||||
Last_query_cost 0.000000
|
||||
SELECT (SELECT a FROM t1 LIMIT 1) x FROM t1 LIMIT 1;
|
||||
x
|
||||
1
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
Variable_name Value
|
||||
Last_query_cost 0.000000
|
||||
SELECT * FROM t1 a, t1 b LIMIT 1;
|
||||
a a
|
||||
1 1
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
Variable_name Value
|
||||
Last_query_cost 4.805836
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -139,4 +139,36 @@ disconnect con3;
|
|||
disconnect con2;
|
||||
disconnect con1;
|
||||
|
||||
|
||||
#
|
||||
# Bug #30377: EXPLAIN loses last_query_cost when used with UNION
|
||||
#
|
||||
|
||||
CREATE TABLE t1 ( a INT );
|
||||
INSERT INTO t1 VALUES (1), (2);
|
||||
|
||||
SELECT a FROM t1 LIMIT 1;
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
|
||||
EXPLAIN SELECT a FROM t1;
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
|
||||
SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY a;
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
|
||||
EXPLAIN SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY a;
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
|
||||
SELECT a IN (SELECT a FROM t1) FROM t1 LIMIT 1;
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
|
||||
SELECT (SELECT a FROM t1 LIMIT 1) x FROM t1 LIMIT 1;
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
|
||||
SELECT * FROM t1 a, t1 b LIMIT 1;
|
||||
SHOW SESSION STATUS LIKE 'Last_query_cost';
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
# End of 5.0 tests
|
||||
|
|
|
@ -1257,6 +1257,28 @@ typedef struct st_lex : public Query_tables_list
|
|||
|
||||
void reset_n_backup_query_tables_list(Query_tables_list *backup);
|
||||
void restore_backup_query_tables_list(Query_tables_list *backup);
|
||||
|
||||
/**
|
||||
@brief check if the statement is a single-level join
|
||||
@return result of the check
|
||||
@retval TRUE The statement doesn't contain subqueries, unions and
|
||||
stored procedure calls.
|
||||
@retval FALSE There are subqueries, UNIONs or stored procedure calls.
|
||||
*/
|
||||
bool is_single_level_stmt()
|
||||
{
|
||||
/*
|
||||
This check exploits the fact that the last added to all_select_list is
|
||||
on its top. So select_lex (as the first added) will be at the tail
|
||||
of the list.
|
||||
*/
|
||||
if (&select_lex == all_selects_list && !sroutines.records)
|
||||
{
|
||||
DBUG_ASSERT(!all_selects_list->next_select_in_list());
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
} LEX;
|
||||
|
||||
struct st_lex_local: public st_lex
|
||||
|
|
|
@ -4369,9 +4369,13 @@ choose_plan(JOIN *join, table_map join_tables)
|
|||
|
||||
/*
|
||||
Store the cost of this query into a user variable
|
||||
Don't update last_query_cost for 'show status' command
|
||||
Don't update last_query_cost for 'show status' command.
|
||||
Don't update last_query_cost for statements that are not "flat joins" :
|
||||
i.e. they have subqueries, unions or call stored procedures.
|
||||
TODO: calculate a correct cost for a query with subqueries and UNIONs.
|
||||
*/
|
||||
if (join->thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
|
||||
if (join->thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS &&
|
||||
join->thd->lex->is_single_level_stmt())
|
||||
join->thd->status_var.last_query_cost= join->best_read;
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue