summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2014-06-25 15:15:38 +0400
committerSergei Petrunia <psergey@askmonty.org>2014-06-25 15:15:38 +0400
commit7711999d8b89d9bcf394e78a79c3c25013e249d6 (patch)
tree4c0a80ad7412c35e074e3ef91b754f71e821289a
parentc3cfb6910a50f7ff094b03f9ef0b5d908f5e4760 (diff)
downloadmariadb-git-7711999d8b89d9bcf394e78a79c3c25013e249d6.tar.gz
MDEV-406: ANALYZE $stmt: add support for BNL join buffering
-rw-r--r--mysql-test/r/analyze_stmt.result37
-rw-r--r--mysql-test/t/analyze_stmt.test25
-rw-r--r--sql/sql_explain.cc10
-rw-r--r--sql/sql_explain.h26
-rw-r--r--sql/sql_join_cache.cc38
-rw-r--r--sql/sql_join_cache.h8
-rw-r--r--sql/sql_select.cc3
-rw-r--r--sql/sql_select.h1
8 files changed, 122 insertions, 26 deletions
diff --git a/mysql-test/r/analyze_stmt.result b/mysql-test/r/analyze_stmt.result
index b07c6679186..adce561c910 100644
--- a/mysql-test/r/analyze_stmt.result
+++ b/mysql-test/r/analyze_stmt.result
@@ -79,4 +79,41 @@ analyze select a, a in (select t0.b from t0 where t0.b+1=t1.b+1) from t1 where t
id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 3 100.00 0.00 Using where
2 DEPENDENT SUBQUERY t0 ALL NULL NULL NULL NULL 10 NULL 100.00 NULL Using where
+drop table t0, t1;
+#
+# Tests for join buffering
+#
+create table t0 (a int, b int);
+insert into t0 values
+(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+create table t1 like t0;
+insert into t1 select * from t0;
+explain select * from t0, t1 where t0.a<5 and t1.a<5;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
+# These should have filtered=50
+analyze select * from t0, t1 where t0.a<5 and t1.a<5;
+id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 10 10 100.00 50.00 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10 100.00 50.00 Using where; Using join buffer (flat, BNL join)
+explain select * from t0, t1 where t0.a<5 and t1.b=t0.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
+# Now, t1 should have filtered=10
+analyze select * from t0, t1 where t0.a<5 and t1.b=t0.b;
+id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 10 10 100.00 50.00 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10 100.00 10.00 Using where; Using join buffer (flat, BNL join)
+explain select * from t0, t1 where t0.a<5 and t1.a<5 and t1.b=t0.b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
+# Now, t1 should have filtered=10
+analyze select * from t0, t1 where t0.a<5 and t1.a<5 and t1.b=t0.b;
+id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 10 10 100.00 50.00 Using where
+1 SIMPLE t1 ALL NULL NULL NULL NULL 10 10 100.00 10.00 Using where; Using join buffer (flat, BNL join)
drop table t0,t1;
+# TODO: Check what is counted for "range checked for each record".
diff --git a/mysql-test/t/analyze_stmt.test b/mysql-test/t/analyze_stmt.test
index a59c4017625..ab47fa52165 100644
--- a/mysql-test/t/analyze_stmt.test
+++ b/mysql-test/t/analyze_stmt.test
@@ -61,5 +61,30 @@ analyze select a, a in (select t0.b from t0 where t0.b+1=t1.b+1) from t1;
--echo # Try a subquery that is never executed
analyze select a, a in (select t0.b from t0 where t0.b+1=t1.b+1) from t1 where t1.a > 5;
+drop table t0, t1;
+
+--echo #
+--echo # Tests for join buffering
+--echo #
+create table t0 (a int, b int);
+insert into t0 values
+ (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+create table t1 like t0;
+insert into t1 select * from t0;
+
+explain select * from t0, t1 where t0.a<5 and t1.a<5;
+--echo # These should have filtered=50
+analyze select * from t0, t1 where t0.a<5 and t1.a<5;
+
+explain select * from t0, t1 where t0.a<5 and t1.b=t0.b;
+--echo # Now, t1 should have filtered=10
+analyze select * from t0, t1 where t0.a<5 and t1.b=t0.b;
+
+explain select * from t0, t1 where t0.a<5 and t1.a<5 and t1.b=t0.b;
+--echo # Now, t1 should have filtered=10
+analyze select * from t0, t1 where t0.a<5 and t1.a<5 and t1.b=t0.b;
+
drop table t0,t1;
+--echo # TODO: Check what is counted for "range checked for each record".
+
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index adfceae346c..af51c5fc382 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -585,12 +585,10 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai
}
else
{
- double r_filtered;
- if (tracker.r_rows > 0)
- r_filtered= 100.0 * (double)tracker.r_rows_after_table_cond / tracker.r_rows;
- else
- r_filtered= 100.0;
- item_list.push_back(new Item_float(r_filtered, 2));
+ double r_filtered= tracker.get_filtered_after_where();
+ if (bka_type.is_using_jbuf())
+ r_filtered *= jbuf_tracker.get_filtered_after_where();
+ item_list.push_back(new Item_float(r_filtered*100.0, 2));
}
}
diff --git a/sql/sql_explain.h b/sql/sql_explain.h
index 7aa62111a0a..a36f1676c57 100644
--- a/sql/sql_explain.h
+++ b/sql/sql_explain.h
@@ -19,13 +19,13 @@ class Table_access_tracker
{
public:
Table_access_tracker() :
- r_scans(0), r_rows(0), r_rows_after_table_cond(0),
+ r_scans(0), r_rows(0), /*r_rows_after_table_cond(0),*/
r_rows_after_where(0)
{}
ha_rows r_scans; /* How many scans were ran on this join_tab */
ha_rows r_rows; /* How many rows we've got after that */
- ha_rows r_rows_after_table_cond; /* Rows after applying the table condition */
+// ha_rows r_rows_after_table_cond; /* Rows after applying the table condition */
ha_rows r_rows_after_where; /* Rows after applying attached part of WHERE */
bool has_scans() { return (r_scans != 0); }
@@ -33,6 +33,17 @@ public:
{
return r_scans ? (ha_rows)rint((double) r_rows / r_scans): 0;
}
+
+ double get_filtered_after_where()
+ {
+ double r_filtered;
+ if (r_rows > 0)
+ r_filtered= (double)r_rows_after_where / r_rows;
+ else
+ r_filtered= 1.0;
+
+ return r_filtered;
+ }
};
@@ -371,13 +382,17 @@ enum explain_extra_tag
};
-typedef struct st_explain_bka_type
+class EXPLAIN_BKA_TYPE
{
+public:
+ EXPLAIN_BKA_TYPE() : join_alg(NULL) {}
+
bool incremental;
const char *join_alg;
StringBuffer<64> mrr_type;
-
-} EXPLAIN_BKA_TYPE;
+
+ bool is_using_jbuf() { return (join_alg != NULL); }
+};
/*
@@ -517,6 +532,7 @@ public:
/* ANALYZE members*/
Table_access_tracker tracker;
+ Table_access_tracker jbuf_tracker;
private:
void append_tag_name(String *str, enum explain_extra_tag tag);
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index abd23c344c2..3131af2041c 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -2254,7 +2254,7 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last)
*/
goto finish;
}
-
+
while (!(error= join_tab_scan->next()))
{
if (join->thd->check_killed())
@@ -2271,11 +2271,13 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last)
/* Prepare to read matching candidates from the join buffer */
if (prepare_look_for_matches(skip_last))
continue;
+ join_tab->jbuf_tracker->r_scans++;
uchar *rec_ptr;
/* Read each possible candidate from the buffer and look for matches */
while ((rec_ptr= get_next_candidate_for_match()))
- {
+ {
+ join_tab->jbuf_tracker->r_rows++;
/*
If only the first match is needed, and, it has been already found for
the next record read from the join buffer, then the record is skipped.
@@ -2445,6 +2447,8 @@ inline bool JOIN_CACHE::check_match(uchar *rec_ptr)
if (join_tab->select && join_tab->select->skip_record(join->thd) <= 0)
DBUG_RETURN(FALSE);
+
+ join_tab->jbuf_tracker->r_rows_after_where++;
if (!join_tab->is_last_inner_table())
DBUG_RETURN(TRUE);
@@ -2568,7 +2572,7 @@ finish:
none
*/
-void JOIN_CACHE::save_explain_data(struct st_explain_bka_type *explain)
+void JOIN_CACHE::save_explain_data(EXPLAIN_BKA_TYPE *explain)
{
explain->incremental= MY_TEST(prev_cache);
@@ -2613,14 +2617,14 @@ static void add_mrr_explain_info(String *str, uint mrr_mode, handler *file)
}
}
-void JOIN_CACHE_BKA::save_explain_data(struct st_explain_bka_type *explain)
+void JOIN_CACHE_BKA::save_explain_data(EXPLAIN_BKA_TYPE *explain)
{
JOIN_CACHE::save_explain_data(explain);
add_mrr_explain_info(&explain->mrr_type, mrr_mode, join_tab->table->file);
}
-void JOIN_CACHE_BKAH::save_explain_data(struct st_explain_bka_type *explain)
+void JOIN_CACHE_BKAH::save_explain_data(EXPLAIN_BKA_TYPE *explain)
{
JOIN_CACHE::save_explain_data(explain);
add_mrr_explain_info(&explain->mrr_type, mrr_mode, join_tab->table->file);
@@ -3326,6 +3330,7 @@ int JOIN_TAB_SCAN::open()
{
save_or_restore_used_tabs(join_tab, FALSE);
is_first_record= TRUE;
+ join_tab->tracker->r_scans++;
return join_init_read_record(join_tab);
}
@@ -3364,8 +3369,14 @@ int JOIN_TAB_SCAN::next()
is_first_record= FALSE;
else
err= info->read_record(info);
- if (!err && table->vfield)
- update_virtual_fields(thd, table);
+
+ if (!err)
+ {
+ join_tab->tracker->r_rows++;
+ if (table->vfield)
+ update_virtual_fields(thd, table);
+ }
+
while (!err && select && (skip_rc= select->skip_record(thd)) <= 0)
{
if (thd->check_killed() || skip_rc < 0)
@@ -3375,9 +3386,16 @@ int JOIN_TAB_SCAN::next()
meet the condition pushed to the table join_tab.
*/
err= info->read_record(info);
- if (!err && table->vfield)
- update_virtual_fields(thd, table);
- }
+ if (!err)
+ {
+ join_tab->tracker->r_rows++;
+ if (table->vfield)
+ update_virtual_fields(thd, table);
+ }
+ }
+
+ if (!err)
+ join_tab->tracker->r_rows_after_where++;
return err;
}
diff --git a/sql/sql_join_cache.h b/sql/sql_join_cache.h
index 568cc91ecf7..bc449a3fff9 100644
--- a/sql/sql_join_cache.h
+++ b/sql/sql_join_cache.h
@@ -63,7 +63,7 @@ typedef struct st_cache_field {
class JOIN_TAB_SCAN;
-struct st_explain_bka_type;
+class EXPLAIN_BKA_TYPE;
/*
JOIN_CACHE is the base class to support the implementations of
@@ -659,7 +659,7 @@ public:
enum_nested_loop_state join_records(bool skip_last);
/* Add a comment on the join algorithm employed by the join cache */
- virtual void save_explain_data(struct st_explain_bka_type *explain);
+ virtual void save_explain_data(EXPLAIN_BKA_TYPE *explain);
THD *thd();
@@ -1337,7 +1337,7 @@ public:
/* Check index condition of the joined table for a record from BKA cache */
bool skip_index_tuple(range_id_t range_info);
- void save_explain_data(struct st_explain_bka_type *explain);
+ void save_explain_data(EXPLAIN_BKA_TYPE *explain);
};
@@ -1428,5 +1428,5 @@ public:
/* Check index condition of the joined table for a record from BKAH cache */
bool skip_index_tuple(range_id_t range_info);
- void save_explain_data(struct st_explain_bka_type *explain);
+ void save_explain_data(EXPLAIN_BKA_TYPE *explain);
};
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 5c1c69e4d82..c4343b577a0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -17731,7 +17731,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
There is no select condition or the attached pushed down
condition is true => a match is found.
*/
- join_tab->tracker->r_rows_after_table_cond++;
+ join_tab->tracker->r_rows_after_where++;
bool found= 1;
while (join_tab->first_unmatched && found)
{
@@ -23308,6 +23308,7 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
eta->quick_info= NULL;
tab->tracker= &eta->tracker;
+ tab->jbuf_tracker= &eta->jbuf_tracker;
/* id */
if (tab->bush_root_tab)
diff --git a/sql/sql_select.h b/sql/sql_select.h
index c1eadd90fcb..ea72828f267 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -252,6 +252,7 @@ typedef struct st_join_table {
enum explain_extra_tag info;
Table_access_tracker *tracker;
+ Table_access_tracker *jbuf_tracker;
/*
Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra'
column, or 0 if there is no info.