From e5bab33a2a4a97261b70ac7c5ef4f4f694896109 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 26 Aug 2010 17:14:18 +0200 Subject: Bug#53806: Wrong estimates for range query in partitioned MyISAM table Bug#46754: 'rows' field doesn't reflect partition pruning The EXPLAIN's result in 'rows' field was evaluated to number of rows when the table was opened (not from the table cache) and only the partitions left after pruning was updated with its correct number of rows. The evaluation of the 'rows' field was using handler::records() which is a potentially expensive call, and ignores the partitioning pruning. The fix was to use the handlers stats.records after updating it with ::info(HA_STATUS_VARIABLE) instead. mysql-test/r/partition_pruning.result: updated result mysql-test/t/partition_pruning.test: Added test. sql/sql_select.cc: Use ::info + stats.records instead of ::records(). --- sql/sql_select.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'sql/sql_select.cc') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7ee1762295f..9a824b0810a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16640,7 +16640,15 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, if (tab->select && tab->select->quick) examined_rows= tab->select->quick->records; else if (tab->type == JT_NEXT || tab->type == JT_ALL) - examined_rows= tab->limit ? tab->limit : tab->table->file->records(); + { + if (tab->limit) + examined_rows= tab->limit; + else + { + tab->table->file->info(HA_STATUS_VARIABLE); + examined_rows= tab->table->file->stats.records; + } + } else examined_rows=(ha_rows)join->best_positions[i].records_read; -- cgit v1.2.1 From 446cc653c0ab13a6fec8ab54de9f5596389b08bc Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Tue, 7 Sep 2010 09:58:05 +0200 Subject: Bug#54543: update ignore with incorrect subquery leads to assertion failure: inited==INDEX When an error occurs while sending the data in a temporary table there was no cleanup performed. This caused a failed assertion in the case when different access methods were used for populating the table vs. retrieving the data from the table if IGNORE was specified and sql_safe_updates = 0. In this case execution continues, but the handler expects to continue with the access method used for row retrieval. Fixed by doing the cleanup even if errors occur. --- sql/sql_select.cc | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'sql/sql_select.cc') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4a32ca34790..f550f75c8b8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11157,22 +11157,20 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) if (error == NESTED_LOOP_NO_MORE_ROWS) error= NESTED_LOOP_OK; + if (table == NULL) // If sending data to client + /* + The following will unlock all cursors if the command wasn't an + update command + */ + join->join_free(); // Unlock all cursors if (error == NESTED_LOOP_OK) { /* Sic: this branch works even if rc != 0, e.g. when send_data above returns an error. */ - if (!table) // If sending data to client - { - /* - The following will unlock all cursors if the command wasn't an - update command - */ - join->join_free(); // Unlock all cursors - if (join->result->send_eof()) - rc= 1; // Don't send error - } + if (table == NULL && join->result->send_eof()) // If sending data to client + rc= 1; // Don't send error DBUG_PRINT("info",("%ld records output", (long) join->send_records)); } else -- cgit v1.2.1 From 3beeb5d045241afb9d3733fba8dd4ec6e5b9dd86 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Mon, 13 Sep 2010 13:33:19 +0200 Subject: Bug #50394: Regression in EXPLAIN with index scan, LIMIT, GROUP BY and ORDER BY computed col GROUP BY implies ORDER BY in the MySQL dialect of SQL. Therefore, when an index on the first table in the query is used, and that index satisfies ordering according to the GROUP BY clause, the query optimizer estimates the number of tuples that need to be read from this index. If there is a LIMIT clause, table statistics on tables following this 'sort table' are employed. There may be a separate ORDER BY clause however, which mandates reading the whole 'sort table' anyway. But the previous estimate was left untouched. Fixed by removing the estimate from EXPLAIN output if GROUP BY is used in conjunction with an ORDER BY clause that mandates using a temporary table. --- sql/sql_select.cc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sql/sql_select.cc') diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f550f75c8b8..605819a1646 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1486,6 +1486,15 @@ JOIN::optimize() } if (order) { + /* + Do we need a temporary table due to the ORDER BY not being equal to + the GROUP BY? The call to test_if_skip_sort_order above tests for the + GROUP BY clause only and hence is not valid in this case. So the + estimated number of rows to be read from the first table is not valid. + We clear it here so that it doesn't show up in EXPLAIN. + */ + if (need_tmp && (select_options & SELECT_DESCRIBE) != 0) + join_tab[const_tables].limit= 0; /* Force using of tmp table if sorting by a SP or UDF function due to their expensive and probably non-deterministic nature. -- cgit v1.2.1