diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2012-07-19 15:52:19 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2012-07-19 15:52:19 +0400 |
commit | ab70b76d9c4eaafde3a4c639bd280d2ccb1d2999 (patch) | |
tree | b96053e78a1e7fcb36a8fa17a31ec9478bc84ca7 | |
parent | 678b4f5dea6edb146fc1877b384d602f5afcac03 (diff) | |
download | mariadb-git-ab70b76d9c4eaafde3a4c639bd280d2ccb1d2999.tar.gz |
BUG#992942 & MDEV-325: Pre-liminary commit for testing
-rw-r--r-- | mysql-test/r/show_explain.result | 60 | ||||
-rw-r--r-- | mysql-test/t/show_explain.test | 56 | ||||
-rw-r--r-- | sql/sql_select.cc | 134 | ||||
-rw-r--r-- | sql/sql_select.h | 10 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 |
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, |