summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2012-07-19 15:52:19 +0400
committerSergey Petrunya <psergey@askmonty.org>2012-07-19 15:52:19 +0400
commitab70b76d9c4eaafde3a4c639bd280d2ccb1d2999 (patch)
treeb96053e78a1e7fcb36a8fa17a31ec9478bc84ca7
parent678b4f5dea6edb146fc1877b384d602f5afcac03 (diff)
downloadmariadb-git-ab70b76d9c4eaafde3a4c639bd280d2ccb1d2999.tar.gz
BUG#992942 & MDEV-325: Pre-liminary commit for testing
-rw-r--r--mysql-test/r/show_explain.result60
-rw-r--r--mysql-test/t/show_explain.test56
-rw-r--r--sql/sql_select.cc134
-rw-r--r--sql/sql_select.h10
-rw-r--r--sql/sql_show.cc2
5 files changed, 250 insertions, 12 deletions
diff --git a/mysql-test/r/show_explain.result b/mysql-test/r/show_explain.result
index 2851e775280..d4161a6ac06 100644
--- a/mysql-test/r/show_explain.result
+++ b/mysql-test/r/show_explain.result
@@ -825,9 +825,67 @@ pk data
19 data1
20 data1
drop table t1;
-drop table t0;
#
# Check that the I_S table is invisible
#
select table_name from information_schema.tables where table_schema='information_schema' and table_name like '%explain%';
table_name
+#
+# MDEV-325: SHOW EXPLAIN: Plan produced by SHOW EXPLAIN is different from standard EXPLAIN: type ALL vs 'index_merge'..
+#
+CREATE TABLE t1 (a INT, b INT, KEY(a), KEY(b)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,0),(128,5050),(5372,8),(234,7596),(2,0),(2907,8930),(1,0),
+(0,5224),(8,7638),(960,5),(9872,1534),(0,2295),(3408,9809),
+(7,0),(1168,0),(2089,5570),(0,205),(88,1018),(0,26528),
+(0,0),(4,5567),(1444,145),(6,0),(1,7535),(7793,534),(70,9),
+(178,1),(44,5),(189,0),(3,0);
+EXPLAIN
+SELECT a+SLEEP(0.01) FROM t1
+WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129
+ORDER BY b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using filesort
+set @show_explain_probe_select_id=1;
+set debug_dbug='d,show_explain_probe_join_exec_start';
+SELECT a+SLEEP(0.01) FROM t1
+WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129
+ORDER BY b;
+show explain for $thr2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using filesort
+Warnings:
+Note 1003 SELECT a+SLEEP(0.01) FROM t1
+WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129
+ORDER BY b
+a+SLEEP(0.01)
+0
+5372
+70
+0
+0
+0
+0
+set @show_explain_probe_select_id=1;
+set debug_dbug='d,show_explain_probe_do_select';
+SELECT a+SLEEP(0.01) FROM t1
+WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129
+ORDER BY b;
+show explain for $thr2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 8 Using sort_union(a,b); Using where; Using filesort
+Warnings:
+Note 1003 SELECT a+SLEEP(0.01) FROM t1
+WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129
+ORDER BY b
+a+SLEEP(0.01)
+0
+5372
+70
+0
+0
+0
+0
+set debug_dbug='';
+drop table t1;
+drop table t0;
diff --git a/mysql-test/t/show_explain.test b/mysql-test/t/show_explain.test
index 2cb3ab6924a..61d1a9398c4 100644
--- a/mysql-test/t/show_explain.test
+++ b/mysql-test/t/show_explain.test
@@ -837,6 +837,7 @@ select * from t1 where pk between 10 and 20 for update;
# run SHOW EXPLAIN on a frozen thread
connection default;
+let $save_wait_condition= $wait_condition;
let $wait_condition= select State='Sending data' from information_schema.processlist where id=$thr2;
let $thr_default=`select connection_id()`;
--source include/wait_condition.inc
@@ -864,14 +865,59 @@ reap;
drop table t1;
disconnect con3;
disconnect con2;
-
-## TODO: Test this: have several SHOW EXPLAIN requests be queued up for a
-## thread and served together.
-
-drop table t0;
+let $wait_condition= $save_wait_condition;
--echo #
--echo # Check that the I_S table is invisible
--echo #
select table_name from information_schema.tables where table_schema='information_schema' and table_name like '%explain%';
+--echo #
+--echo # MDEV-325: SHOW EXPLAIN: Plan produced by SHOW EXPLAIN is different from standard EXPLAIN: type ALL vs 'index_merge'..
+--echo #
+CREATE TABLE t1 (a INT, b INT, KEY(a), KEY(b)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES
+(8,0),(128,5050),(5372,8),(234,7596),(2,0),(2907,8930),(1,0),
+(0,5224),(8,7638),(960,5),(9872,1534),(0,2295),(3408,9809),
+(7,0),(1168,0),(2089,5570),(0,205),(88,1018),(0,26528),
+(0,0),(4,5567),(1444,145),(6,0),(1,7535),(7793,534),(70,9),
+(178,1),(44,5),(189,0),(3,0);
+
+EXPLAIN
+SELECT a+SLEEP(0.01) FROM t1
+WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129
+ORDER BY b;
+
+set @show_explain_probe_select_id=1;
+set debug_dbug='d,show_explain_probe_join_exec_start';
+--send
+SELECT a+SLEEP(0.01) FROM t1
+WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129
+ORDER BY b;
+
+connection default;
+--source include/wait_condition.inc
+evalp show explain for $thr2;
+
+connection con1;
+reap;
+
+set @show_explain_probe_select_id=1;
+set debug_dbug='d,show_explain_probe_do_select';
+--send
+SELECT a+SLEEP(0.01) FROM t1
+WHERE a IN ( 255, 0 ) OR b BETWEEN 6 AND 129
+ORDER BY b;
+
+connection default;
+--source include/wait_condition.inc
+evalp show explain for $thr2;
+
+connection con1;
+reap;
+
+set debug_dbug='';
+
+drop table t1;
+drop table t0;
+
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 486a55cf50e..599590cc313 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -10686,6 +10686,9 @@ void JOIN::cleanup(bool full)
*/
if (full)
{
+ if (pre_sort_join_tab)
+ clean_pre_sort_join_tab();
+
if (tmp_join)
tmp_table_param.copy_field= 0;
group_fields.delete_elements();
@@ -18908,6 +18911,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
TABLE *table;
SQL_SELECT *select;
JOIN_TAB *tab;
+ int err= 0;
+ bool quick_created= FALSE;
DBUG_ENTER("create_sort_index");
if (join->table_count == join->const_tables)
@@ -18915,6 +18920,43 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
tab= join->join_tab + join->const_tables;
table= tab->table;
select= tab->select;
+
+ JOIN_TAB *save_pre_sort_join_tab= NULL;
+ if (join->pre_sort_join_tab)
+ {
+ /*
+ we've already been in this function, and stashed away the original access
+ method in join->pre_sort_join_tab, restore it now.
+ */
+
+ /* First, restore state of the handler */
+ if (join->pre_sort_index != MAX_KEY)
+ {
+ if (table->file->ha_index_or_rnd_end())
+ goto err;
+ if (join->pre_sort_idx_pushed_cond)
+ {
+ table->file->idx_cond_push(join->pre_sort_index,
+ join->pre_sort_idx_pushed_cond);
+ }
+ }
+ else
+ {
+ if (table->file->ha_index_or_rnd_end() ||
+ table->file->ha_rnd_init(TRUE))
+ goto err;
+ }
+
+ /* Second, restore access method parameters */
+ tab->records= join->pre_sort_join_tab->records;
+ tab->select= join->pre_sort_join_tab->select;
+ tab->select_cond= join->pre_sort_join_tab->select_cond;
+ tab->type= join->pre_sort_join_tab->type;
+ tab->read_first_record= join->pre_sort_join_tab->read_first_record;
+
+ save_pre_sort_join_tab= join->pre_sort_join_tab;
+ join->pre_sort_join_tab= NULL;
+ }
/* Currently ORDER BY ... LIMIT is not supported in subqueries. */
DBUG_ASSERT(join->group_list || !join->is_in_subquery());
@@ -18970,6 +19012,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
get_quick_select_for_ref(thd, table, &tab->ref,
tab->found_records))))
goto err;
+ quick_created= TRUE;
}
}
@@ -18985,7 +19028,37 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
table->sort.found_records=filesort(thd, table,join->sortorder, length,
select, filesort_limit, 0,
&examined_rows);
+
+ if (quick_created)
+ {
+ /* This will delete the quick select. */
+ select->cleanup();
+ }
+
+ if (!join->pre_sort_join_tab)
+ {
+ if (save_pre_sort_join_tab)
+ join->pre_sort_join_tab= save_pre_sort_join_tab;
+ else if (!(join->pre_sort_join_tab= (JOIN_TAB*)thd->alloc(sizeof(JOIN_TAB))))
+ goto err;
+ }
+
+ *(join->pre_sort_join_tab)= *tab;
+
+ if (table->file->inited == handler::INDEX)
+ {
+ // Save index #, save index condition
+ join->pre_sort_index= table->file->active_index;
+ join->pre_sort_idx_pushed_cond= table->file->pushed_idx_cond;
+ // no need to save key_read?
+ err= table->file->ha_index_end();
+ }
+ else
+ join->pre_sort_index= MAX_KEY;
+
+ /*TODO: here, close the index scan, cancel index-only read. */
tab->records= table->sort.found_records; // For SQL_CALC_ROWS
+#if 0
if (select)
{
/*
@@ -19002,23 +19075,65 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
tablesort_result_cache= table->sort.io_cache;
table->sort.io_cache= NULL;
- select->cleanup(); // filesort did select
+ // select->cleanup(); // filesort did select
table->quick_keys.clear_all(); // as far as we cleanup select->quick
table->intersect_keys.clear_all();
table->sort.io_cache= tablesort_result_cache;
}
+#endif
+ tab->select=NULL;
tab->set_select_cond(NULL, __LINE__);
- tab->last_inner= 0;
- tab->first_unmatched= 0;
+// tab->last_inner= 0;
+// tab->first_unmatched= 0;
tab->type=JT_ALL; // Read with normal read_record
tab->read_first_record= join_init_read_record;
+ tab->table->file->ha_index_or_rnd_end();
+
+ if (err)
+ goto err;
+
tab->join->examined_rows+=examined_rows;
- table->disable_keyread(); // Restore if we used indexes
DBUG_RETURN(table->sort.found_records == HA_POS_ERROR);
err:
DBUG_RETURN(-1);
}
+void JOIN::clean_pre_sort_join_tab()
+{
+ TABLE *table= pre_sort_join_tab->table;
+ /*
+ Note: we can come here for fake_select_lex object. That object will have
+ the table already deleted by st_select_lex_unit::cleanup().
+ We rely on that fake_select_lex didn't have quick select.
+ */
+#if 0
+ if (pre_sort_join_tab->select && pre_sort_join_tab->select->quick)
+ {
+ /*
+ We need to preserve tablesort's output resultset here, because
+ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT (called by
+ SQL_SELECT::cleanup()) may free it assuming it's the result of the quick
+ select operation that we no longer need. Note that all the other parts of
+ this data structure are cleaned up when
+ QUICK_INDEX_MERGE_SELECT::get_next encounters end of data, so the next
+ SQL_SELECT::cleanup() call changes sort.io_cache alone.
+ */
+ IO_CACHE *tablesort_result_cache;
+
+ tablesort_result_cache= table->sort.io_cache;
+ table->sort.io_cache= NULL;
+ pre_sort_join_tab->select->cleanup();
+ table->quick_keys.clear_all(); // as far as we cleanup select->quick
+ table->intersect_keys.clear_all();
+ table->sort.io_cache= tablesort_result_cache;
+ }
+#endif
+ //table->disable_keyread(); // Restore if we used indexes
+ if (pre_sort_join_tab->select && pre_sort_join_tab->select->quick)
+ {
+ pre_sort_join_tab->select->cleanup();
+ }
+}
/*****************************************************************************
Remove duplicates from tmp table
This should be recoded to add a unique index to the table and remove
@@ -21502,6 +21617,7 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
tmp4.length(0);
quick_type= -1;
QUICK_SELECT_I *quick= NULL;
+ JOIN_TAB *saved_join_tab= NULL;
/* Don't show eliminated tables */
if (table->map & join->eliminated_tables)
@@ -21510,6 +21626,12 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
continue;
}
+ if (tab == first_top_tab && pre_sort_join_tab)
+ {
+ saved_join_tab= tab;
+ tab= pre_sort_join_tab;
+ }
+
item_list.empty();
/* id */
item_list.push_back(new Item_uint((uint32)select_id));
@@ -21656,7 +21778,6 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
keylen_str_buf);
tmp3.append(keylen_str_buf, length, cs);
/*<<<<<<< TREE
- }
if ((is_hj || tab->type==JT_RANGE || tab->type == JT_INDEX_MERGE) &&
tab->select && tab->select->quick)
=======*/
@@ -21977,6 +22098,9 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
item_list.push_back(new Item_string(str, len, cs));
}
+ if (saved_join_tab)
+ tab= saved_join_tab;
+
// For next iteration
used_tables|=table->map;
if (result->send_data(item_list))
diff --git a/sql/sql_select.h b/sql/sql_select.h
index b78ac10d35f..d0677f069e7 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -903,6 +903,14 @@ protected:
public:
JOIN_TAB *join_tab, **best_ref;
+
+ /*
+ Saved join_tab for pre_sorting. create_sort_index() will save here..
+ */
+ JOIN_TAB *pre_sort_join_tab;
+ uint pre_sort_index;
+ Item *pre_sort_idx_pushed_cond;
+ void clean_pre_sort_join_tab();
/*
For "Using temporary+Using filesort" queries, JOIN::join_tab can point to
@@ -1293,6 +1301,8 @@ public:
outer_ref_cond= pseudo_bits_cond= NULL;
in_to_exists_where= NULL;
in_to_exists_having= NULL;
+
+ pre_sort_join_tab= NULL;
}
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 03bed2689df..bc8e01491e6 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -8495,7 +8495,7 @@ ST_FIELD_INFO show_explain_fields_info[]=
SKIP_OPEN_TABLE},
{"table", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0 /*value*/, MY_I_S_MAYBE_NULL,
"table", SKIP_OPEN_TABLE},
- {"type", 10, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, "type", SKIP_OPEN_TABLE},
+ {"type", 11, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, "type", SKIP_OPEN_TABLE},
{"possible_keys", NAME_CHAR_LEN*MAX_KEY, MYSQL_TYPE_STRING, 0/*value*/,
MY_I_S_MAYBE_NULL, "possible_keys", SKIP_OPEN_TABLE},
{"key", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0/*value*/, MY_I_S_MAYBE_NULL,