Commit dc1d6213 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-30806: ANALYZE FORMAT=JSON: better support for BNL and BNL-H joins

In block-nl-join, add:

- r_loops - this shows how many incoming record combinations this
  query plan node had.

- r_effective_rows - this shows the average number of matching rows
  that this table had for each incoming record combination. This is
  comparable with r_rows in non-blocked access methods.
  For BNL-joins, it is always equal to
   $.table.r_rows * $.table.r_filtered
  For BNL-H joins the value cannot be computed from other values

Reviewed by: Monty <monty@mariadb.org>
parent 169def14
......@@ -151,7 +151,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "1Kb",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 20,
"r_filtered": 100,
"r_effective_rows": 60
}
}
}
......@@ -192,7 +194,9 @@ ANALYZE
"buffer_size": "1Kb",
"join_type": "BNL",
"attached_condition": "tbl1.c > tbl2.c",
"r_filtered": 15.83333333
"r_loops": 20,
"r_filtered": 15.83333333,
"r_effective_rows": 60
}
}
}
......@@ -652,7 +656,9 @@ ANALYZE
"buffer_size": "65",
"join_type": "BNL",
"attached_condition": "<in_optimizer>(t2.b,t2.b in (subquery#2))",
"r_filtered": null
"r_loops": 2,
"r_filtered": null,
"r_effective_rows": 0
},
"subqueries": [
{
......@@ -742,7 +748,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "1",
"join_type": "BNL",
"r_filtered": null
"r_loops": 2,
"r_filtered": null,
"r_effective_rows": 0
},
"subqueries": [
{
......@@ -774,7 +782,9 @@ ANALYZE
"buffer_size": "65",
"join_type": "BNL",
"attached_condition": "t2.f2 = t3.f3",
"r_filtered": null
"r_loops": 0,
"r_filtered": null,
"r_effective_rows": null
}
}
}
......@@ -849,3 +859,123 @@ ANALYZE
}
}
drop table t0,t1,t2;
#
# MDEV-30806: ANALYZE FORMAT=JSON: better support for BNL and BNL-H joins
#
create table t10 (
a int,
b int
);
insert into t10 select seq, seq/3 from seq_0_to_999;
create table t11 (
a int,
b int
);
insert into t11 select seq, seq/5 from seq_0_to_999;
analyze table t10,t11 persistent for all;
Table Op Msg_type Msg_text
test.t10 analyze status Engine-independent statistics collected
test.t10 analyze status OK
test.t11 analyze status Engine-independent statistics collected
test.t11 analyze status OK
analyze format=json
select * from t10, t11
where
t10.a < 700 and
t11.a < 100
and t10.b=t11.b;
ANALYZE
{
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
"table_name": "t11",
"access_type": "ALL",
"r_loops": 1,
"rows": 1000,
"r_rows": 1000,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 10.15625,
"r_filtered": 10,
"attached_condition": "t11.a < 100"
},
"block-nl-join": {
"table": {
"table_name": "t10",
"access_type": "ALL",
"r_loops": 1,
"rows": 1000,
"r_rows": 1000,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 70.3125,
"r_filtered": 70,
"attached_condition": "t10.a < 700"
},
"buffer_type": "flat",
"buffer_size": "1Kb",
"join_type": "BNL",
"attached_condition": "t10.b = t11.b",
"r_loops": 100,
"r_filtered": 0.424285714,
"r_effective_rows": 700
}
}
}
set @tmp=@@join_cache_level, join_cache_level=6;
analyze format=json
select * from t10, t11
where
t10.a < 700 and
t11.a < 100
and t10.b=t11.b;
ANALYZE
{
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
"table_name": "t11",
"access_type": "ALL",
"r_loops": 1,
"rows": 1000,
"r_rows": 1000,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 10.15625,
"r_filtered": 10,
"attached_condition": "t11.a < 100 and t11.b is not null"
},
"block-nl-join": {
"table": {
"table_name": "t10",
"access_type": "hash_ALL",
"key": "#hash#$hj",
"key_length": "5",
"used_key_parts": ["b"],
"ref": ["test.t11.b"],
"r_loops": 1,
"rows": 1000,
"r_rows": 1000,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 70.3125,
"r_filtered": 70,
"attached_condition": "t10.a < 700"
},
"buffer_type": "flat",
"buffer_size": "3Kb",
"join_type": "BNLH",
"attached_condition": "t10.b = t11.b",
"r_loops": 100,
"r_filtered": 100,
"r_effective_rows": 2.97
}
}
}
set join_cache_level=@tmp;
drop table t10, t11;
......@@ -226,3 +226,45 @@ create table t2 as select * from t1;
--source include/analyze-format.inc
analyze format=json select a, (select t2.b from t2 where t2.a<t1.a order by t2.c limit 1) from t1 where t1.a<0;
drop table t0,t1,t2;
--echo #
--echo # MDEV-30806: ANALYZE FORMAT=JSON: better support for BNL and BNL-H joins
--echo #
--source include/have_sequence.inc
create table t10 (
a int,
b int
);
insert into t10 select seq, seq/3 from seq_0_to_999;
create table t11 (
a int,
b int
);
insert into t11 select seq, seq/5 from seq_0_to_999;
analyze table t10,t11 persistent for all;
--source include/analyze-format.inc
analyze format=json
select * from t10, t11
where
t10.a < 700 and
t11.a < 100
and t10.b=t11.b;
set @tmp=@@join_cache_level, join_cache_level=6;
--source include/analyze-format.inc
analyze format=json
select * from t10, t11
where
t10.a < 700 and
t11.a < 100
and t10.b=t11.b;
set join_cache_level=@tmp;
drop table t10, t11;
......@@ -441,7 +441,9 @@ ANALYZE
"buffer_size": "65",
"join_type": "BNL",
"attached_condition": "t3.a = t0.a",
"r_filtered": 10
"r_loops": 10,
"r_filtered": 10,
"r_effective_rows": 10
}
}
}
......@@ -516,7 +518,9 @@ ANALYZE
"buffer_size": "119",
"join_type": "BNL",
"attached_condition": "t5.a = t6.a",
"r_filtered": 21.42857143
"r_loops": 4,
"r_filtered": 21.42857143,
"r_effective_rows": 7
}
}
}
......
......@@ -334,7 +334,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "119",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 2,
"r_filtered": 100,
"r_effective_rows": 2
}
}
},
......@@ -370,7 +372,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "119",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 2,
"r_filtered": 100,
"r_effective_rows": 2
}
}
}
......@@ -435,7 +439,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "119",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 2,
"r_filtered": 100,
"r_effective_rows": 2
}
}
},
......@@ -471,7 +477,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "119",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 2,
"r_filtered": 100,
"r_effective_rows": 2
}
}
}
......
......@@ -453,7 +453,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "119",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 3,
"r_filtered": 100,
"r_effective_rows": 3
}
}
},
......@@ -489,7 +491,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "119",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 2,
"r_filtered": 100,
"r_effective_rows": 3
}
}
}
......@@ -553,7 +557,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "119",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 3,
"r_filtered": 100,
"r_effective_rows": 3
}
}
},
......@@ -589,7 +595,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "119",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 2,
"r_filtered": 100,
"r_effective_rows": 3
}
}
}
......
......@@ -1544,7 +1544,9 @@ ANALYZE
"buffer_size": "400",
"join_type": "BKA",
"mrr_type": "Rowid-ordered scan",
"r_filtered": 100
"r_loops": 10,
"r_filtered": 100,
"r_effective_rows": 1
}
}
}
......
......@@ -395,7 +395,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "256Kb",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 3,
"r_filtered": 100,
"r_effective_rows": 3
}
}
}
......@@ -478,7 +480,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "256Kb",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 3,
"r_filtered": 100,
"r_effective_rows": 3
}
}
}
......
......@@ -426,7 +426,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "65",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 5,
"r_filtered": 100,
"r_effective_rows": 7
}
}
}
......@@ -509,7 +511,9 @@ ANALYZE
"buffer_type": "flat",
"buffer_size": "65",
"join_type": "BNL",
"r_filtered": 100
"r_loops": 5,
"r_filtered": 100,
"r_effective_rows": 7
}
}
}
......
......@@ -3685,7 +3685,9 @@ ANALYZE
"join_type": "BKA",
"mrr_type": "Rowid-ordered scan",
"attached_condition": "a.atp = 1",
"r_filtered": 100
"r_loops": 3,
"r_filtered": 100,
"r_effective_rows": 1
},
"block-nl-join": {
"table": {
......@@ -3709,7 +3711,9 @@ ANALYZE
"join_type": "BKA",
"mrr_type": "Rowid-ordered scan",
"attached_condition": "fi.fh in (6311439873746261694,-397087483897438286,8518228073041491534,-5420422472375069774)",
"r_filtered": 40
"r_loops": 3,
"r_filtered": 40,
"r_effective_rows": 26.66666667
}
}
}
......
......@@ -158,6 +158,25 @@ class Time_and_counter_tracker: public Exec_time_tracker
if (unlikely((tracker)->timed)) \
{ (tracker)->stop_tracking(thd); }
/*
Just a counter to increment one value. Wrapped in a class to be uniform
with other counters used by ANALYZE.
*/
class Counter_tracker
{
public:
Counter_tracker() : r_scans(0) {}
ha_rows r_scans;
inline void on_scan_init() { r_scans++; }
bool has_scans() const { return (r_scans != 0); }
ha_rows get_loops() const { return r_scans; }
};
/*
A class for collecting read statistics.
......@@ -171,17 +190,13 @@ class Time_and_counter_tracker: public Exec_time_tracker
class Table_access_tracker
{
public:
Table_access_tracker() :
r_scans(0), r_rows(0), /*r_rows_after_table_cond(0),*/
r_rows_after_where(0)
Table_access_tracker() : r_scans(0), r_rows(0), r_rows_after_where(0)
{}
ha_rows r_scans; /* How many scans were ran on this join_tab */
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_where; /* Rows after applying attached part of WHERE */
bool has_scans() const { return (r_scans != 0); }
ha_rows get_loops() const { return r_scans; }
double get_avg_rows() const
{
return r_scans
......@@ -200,6 +215,9 @@ class Table_access_tracker
inline void on_scan_init() { r_scans++; }
inline void on_record_read() { r_rows++; }
inline void on_record_after_where() { r_rows_after_where++; }
bool has_scans() const { return (r_scans != 0); }
ha_rows get_loops() const { return r_scans; }
};
......
......@@ -1891,12 +1891,29 @@ void Explain_table_access::print_explain_json(Explain_query *query,
if (is_analyze)
{
//writer->add_member("r_loops").add_ll(jbuf_tracker.get_loops());
writer->add_member("r_loops").add_ll(jbuf_loops_tracker.get_loops());
writer->add_member("r_filtered");
if (jbuf_tracker.has_scans())
writer->add_double(jbuf_tracker.get_filtered_after_where()*100.0);
else
writer->add_null();
/*
effective_rows is average number of matches we got for an incoming
row. The row is stored in the join buffer and then is read
from there, possibly multiple times. We can't count this number
directly. Infer it as:
total_number_of_row_combinations_considered / r_loops.
*/
writer->add_member("r_effective_rows");
if (jbuf_loops_tracker.has_scans())
{
double loops= (double)jbuf_loops_tracker.get_loops();
double row_combinations= (double)jbuf_tracker.r_rows;
writer->add_double(row_combinations / loops);
}
else
writer->add_null();
}
}
......
......@@ -842,8 +842,12 @@ class Explain_table_access : public Sql_alloc
Exec_time_tracker op_tracker;
Gap_time_tracker extra_time_tracker;
/* When using join buffer: Track the reads from join buffer */
Table_access_tracker jbuf_tracker;
/* When using join buffer: Track the number of incoming record combinations */
Counter_tracker jbuf_loops_tracker;
Explain_rowid_filter *rowid_filter;
int print_explain(select_result_sink *output, uint8 explain_flags,
......
......@@ -21231,6 +21231,8 @@ sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records)
/* The user has aborted the execution of the query */
DBUG_RETURN(NESTED_LOOP_KILLED);
}
join_tab->jbuf_loops_tracker->on_scan_init();
if (!test_if_use_dynamic_range_scan(join_tab))
{
if (!cache->put_record())
......@@ -27393,6 +27395,7 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta,
// psergey-todo: data for filtering!
tracker= &eta->tracker;
jbuf_tracker= &eta->jbuf_tracker;
jbuf_loops_tracker= &eta->jbuf_loops_tracker;
/* Enable the table access time tracker only for "ANALYZE stmt" */
if (thd->lex->analyze_stmt)
......
......@@ -309,6 +309,7 @@ typedef struct st_join_table {
Table_access_tracker *tracker;
Table_access_tracker *jbuf_tracker;
Counter_tracker *jbuf_loops_tracker;
/*
Bitmap of TAB_INFO_* bits that encodes special line for EXPLAIN 'Extra'
column, or 0 if there is no info.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment