Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
0b5d989c
Commit
0b5d989c
authored
Nov 29, 2014
by
Sergei Petrunia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
EXPLAIN FORMAT=JSON: Add support for non-merged semi-joins
parent
2ac3b39e
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
117 additions
and
7 deletions
+117
-7
mysql-test/r/explain_json.result
mysql-test/r/explain_json.result
+42
-0
mysql-test/t/explain_json.test
mysql-test/t/explain_json.test
+6
-0
sql/sql_explain.cc
sql/sql_explain.cc
+25
-1
sql/sql_explain.h
sql/sql_explain.h
+16
-3
sql/sql_lex.cc
sql/sql_lex.cc
+6
-1
sql/sql_select.cc
sql/sql_select.cc
+7
-2
sql/sql_select.h
sql/sql_select.h
+15
-0
No files found.
mysql-test/r/explain_json.result
View file @
0b5d989c
...
@@ -464,4 +464,46 @@ EXPLAIN
...
@@ -464,4 +464,46 @@ EXPLAIN
}
}
}
}
}
}
#
# Non-merged semi-join (aka JTBM)
#
explain format=json
select * from t1 where a in (select max(a) from t1 group by b);
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100,
"attached_condition": "(t1.a is not null)"
},
"table": {
"table_name": "<subquery2>",
"access_type": "eq_ref",
"possible_keys": ["distinct_key"],
"key": "distinct_key",
"key_length": "4",
"used_key_parts": ["max(a)"],
"ref": ["test.t1.a"],
"rows": 1,
"filtered": 100,
"materialized": {
"unique": 1,
"query_block": {
"select_id": 2,
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 10,
"filtered": 100
}
}
}
}
}
}
drop table t1;
drop table t0;
drop table t0;
mysql-test/t/explain_json.test
View file @
0b5d989c
...
@@ -93,5 +93,11 @@ explain format=json
...
@@ -93,5 +93,11 @@ explain format=json
select
*
from
(
select
a
,
count
(
*
)
as
cnt
from
t1
group
by
a
)
as
tbl1
,
t1
as
select
*
from
(
select
a
,
count
(
*
)
as
cnt
from
t1
group
by
a
)
as
tbl1
,
t1
as
tbl2
where
cnt
=
tbl2
.
a
;
tbl2
where
cnt
=
tbl2
.
a
;
--
echo
#
--
echo
# Non-merged semi-join (aka JTBM)
--
echo
#
explain
format
=
json
select
*
from
t1
where
a
in
(
select
max
(
a
)
from
t1
group
by
b
);
drop
table
t1
;
drop
table
t0
;
drop
table
t0
;
sql/sql_explain.cc
View file @
0b5d989c
...
@@ -554,6 +554,19 @@ int Explain_node::print_explain_for_children(Explain_query *query,
...
@@ -554,6 +554,19 @@ int Explain_node::print_explain_for_children(Explain_query *query,
}
}
/*
This tells whether a child subquery should be printed in JSON output.
Derived tables and Non-merged semi-joins should not be printed, because they
are printed inline in Explain_table_access.
*/
bool
is_connection_printable_in_json
(
enum
Explain_node
::
explain_connection_type
type
)
{
return
(
type
!=
Explain_node
::
EXPLAIN_NODE_DERIVED
&&
type
!=
Explain_node
::
EXPLAIN_NODE_NON_MERGED_SJ
);
}
void
Explain_node
::
print_explain_json_for_children
(
Explain_query
*
query
,
void
Explain_node
::
print_explain_json_for_children
(
Explain_query
*
query
,
Json_writer
*
writer
,
Json_writer
*
writer
,
bool
is_analyze
)
bool
is_analyze
)
...
@@ -565,7 +578,8 @@ void Explain_node::print_explain_json_for_children(Explain_query *query,
...
@@ -565,7 +578,8 @@ void Explain_node::print_explain_json_for_children(Explain_query *query,
{
{
Explain_node
*
node
=
query
->
get_node
(
children
.
at
(
i
));
Explain_node
*
node
=
query
->
get_node
(
children
.
at
(
i
));
/* Derived tables are printed inside Explain_table_access objects */
/* Derived tables are printed inside Explain_table_access objects */
if
(
node
->
is_derived_table
)
if
(
!
is_connection_printable_in_json
(
node
->
connection_type
))
continue
;
continue
;
if
(
!
started
)
if
(
!
started
)
...
@@ -1189,6 +1203,16 @@ void Explain_table_access::print_explain_json(Explain_query *query,
...
@@ -1189,6 +1203,16 @@ void Explain_table_access::print_explain_json(Explain_query *query,
node
->
print_explain_json
(
query
,
writer
,
is_analyze
);
node
->
print_explain_json
(
query
,
writer
,
is_analyze
);
writer
->
end_object
();
writer
->
end_object
();
}
}
if
(
non_merged_sjm_number
)
{
/* This is a non-merged semi-join table. Print its contents here */
writer
->
add_member
(
"materialized"
).
start_object
();
writer
->
add_member
(
"unique"
).
add_ll
(
1
);
Explain_node
*
node
=
query
->
get_node
(
non_merged_sjm_number
);
node
->
connection_type
=
Explain_node
::
EXPLAIN_NODE_NON_MERGED_SJ
;
node
->
print_explain_json
(
query
,
writer
,
is_analyze
);
writer
->
end_object
();
}
writer
->
end_object
();
writer
->
end_object
();
}
}
...
...
sql/sql_explain.h
View file @
0b5d989c
...
@@ -77,12 +77,14 @@ const int FAKE_SELECT_LEX_ID= (int)UINT_MAX;
...
@@ -77,12 +77,14 @@ const int FAKE_SELECT_LEX_ID= (int)UINT_MAX;
class
Explain_query
;
class
Explain_query
;
class
Json_writer
;
class
Json_writer
;
/*
/*
A node can be either a SELECT, or a UNION.
A node can be either a SELECT, or a UNION.
*/
*/
class
Explain_node
:
public
Sql_alloc
class
Explain_node
:
public
Sql_alloc
{
{
public:
public:
/* A type specifying what kind of node this is */
enum
explain_node_type
enum
explain_node_type
{
{
EXPLAIN_UNION
,
EXPLAIN_UNION
,
...
@@ -91,16 +93,24 @@ public:
...
@@ -91,16 +93,24 @@ public:
EXPLAIN_DELETE
,
EXPLAIN_DELETE
,
EXPLAIN_INSERT
EXPLAIN_INSERT
};
};
/* How this node is connected */
enum
explain_connection_type
{
EXPLAIN_NODE_OTHER
,
EXPLAIN_NODE_DERIVED
,
/* Materialized derived table */
EXPLAIN_NODE_NON_MERGED_SJ
/* aka JTBM semi-join */
};
Explain_node
()
:
is_derived_table
(
false
)
{}
Explain_node
()
:
connection_type
(
EXPLAIN_NODE_OTHER
)
{}
virtual
enum
explain_node_type
get_type
()
=
0
;
virtual
enum
explain_node_type
get_type
()
=
0
;
virtual
int
get_select_id
()
=
0
;
virtual
int
get_select_id
()
=
0
;
/*
/*
TRUE means this is a derived table. FALSE means otherwise.
How this node is connected to its parent.
(NOTE: EXPLAIN_NODE_NON_MERGED_SJ is set very late currently)
*/
*/
bool
is_derived_tabl
e
;
enum
explain_connection_type
connection_typ
e
;
/*
/*
A node may have children nodes. When a node's explain structure is
A node may have children nodes. When a node's explain structure is
...
@@ -502,6 +512,7 @@ class Explain_table_access : public Sql_alloc
...
@@ -502,6 +512,7 @@ class Explain_table_access : public Sql_alloc
public:
public:
Explain_table_access
()
:
Explain_table_access
()
:
derived_select_number
(
0
),
derived_select_number
(
0
),
non_merged_sjm_number
(
0
),
where_cond
(
NULL
),
where_cond
(
NULL
),
cache_cond
(
NULL
),
cache_cond
(
NULL
),
pushed_index_cond
(
NULL
)
pushed_index_cond
(
NULL
)
...
@@ -525,6 +536,8 @@ public:
...
@@ -525,6 +536,8 @@ public:
find the query plan for the derived table
find the query plan for the derived table
*/
*/
int
derived_select_number
;
int
derived_select_number
;
/* TODO: join with the previous member. */
int
non_merged_sjm_number
;
enum
join_type
type
;
enum
join_type
type
;
...
...
sql/sql_lex.cc
View file @
0b5d989c
...
@@ -4268,8 +4268,13 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
...
@@ -4268,8 +4268,13 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
{
{
SELECT_LEX
*
first
=
first_select
();
SELECT_LEX
*
first
=
first_select
();
Explain_union
*
eu
=
new
(
output
->
mem_root
)
Explain_union
;
Explain_union
*
eu
=
new
(
output
->
mem_root
)
Explain_union
;
if
(
derived
)
if
(
derived
)
eu
->
is_derived_table
=
true
;
eu
->
connection_type
=
Explain_node
::
EXPLAIN_NODE_DERIVED
;
/*
Note: Non-merged semi-joins cannot be made out of UNIONs currently, so we
dont ever set EXPLAIN_NODE_NON_MERGED_SJ.
*/
for
(
SELECT_LEX
*
sl
=
first
;
sl
;
sl
=
sl
->
next_select
())
for
(
SELECT_LEX
*
sl
=
first
;
sl
;
sl
=
sl
->
next_select
())
eu
->
add_select
(
sl
->
select_number
);
eu
->
add_select
(
sl
->
select_number
);
...
...
sql/sql_select.cc
View file @
0b5d989c
...
@@ -23660,8 +23660,13 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
...
@@ -23660,8 +23660,13 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
subselect that used to produce it.
subselect that used to produce it.
*/
*/
eta
->
derived_select_number
=
table
->
derived_select_number
;
eta
->
derived_select_number
=
table
->
derived_select_number
;
/* The same for non-merged semi-joins */
eta
->
non_merged_sjm_number
=
get_non_merged_semijoin_select
();
}
}
/*
/*
Save Query Plan Footprint
Save Query Plan Footprint
...
@@ -23693,7 +23698,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
...
@@ -23693,7 +23698,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
xpl_sel
->
select_type
=
join
->
select_lex
->
type
;
xpl_sel
->
select_type
=
join
->
select_lex
->
type
;
xpl_sel
->
message
=
message
;
xpl_sel
->
message
=
message
;
if
(
select_lex
->
master_unit
()
->
derived
)
if
(
select_lex
->
master_unit
()
->
derived
)
xpl_sel
->
is_derived_table
=
true
;
xpl_sel
->
connection_type
=
Explain_node
::
EXPLAIN_NODE_DERIVED
;
/* Setting xpl_sel->message means that all other members are invalid */
/* Setting xpl_sel->message means that all other members are invalid */
output
->
add_node
(
xpl_sel
);
output
->
add_node
(
xpl_sel
);
}
}
...
@@ -23712,7 +23717,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
...
@@ -23712,7 +23717,7 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table,
xpl_sel
->
select_id
=
join
->
select_lex
->
select_number
;
xpl_sel
->
select_id
=
join
->
select_lex
->
select_number
;
xpl_sel
->
select_type
=
join
->
select_lex
->
type
;
xpl_sel
->
select_type
=
join
->
select_lex
->
type
;
if
(
select_lex
->
master_unit
()
->
derived
)
if
(
select_lex
->
master_unit
()
->
derived
)
xpl_sel
->
is_derived_table
=
true
;
xpl_sel
->
connection_type
=
Explain_node
::
EXPLAIN_NODE_DERIVED
;
JOIN_TAB
*
const
first_top_tab
=
first_breadth_first_tab
(
join
,
WALK_OPTIMIZATION_TABS
);
JOIN_TAB
*
const
first_top_tab
=
first_breadth_first_tab
(
join
,
WALK_OPTIMIZATION_TABS
);
...
...
sql/sql_select.h
View file @
0b5d989c
...
@@ -527,6 +527,21 @@ typedef struct st_join_table {
...
@@ -527,6 +527,21 @@ typedef struct st_join_table {
bool
preread_init
();
bool
preread_init
();
bool
is_sjm_nest
()
{
return
MY_TEST
(
bush_children
);
}
bool
is_sjm_nest
()
{
return
MY_TEST
(
bush_children
);
}
/*
If this join_tab reads a non-merged semi-join (also called jtbm), return
the select's number. Otherwise, return 0.
*/
int
get_non_merged_semijoin_select
()
const
{
Item_in_subselect
*
subq
;
if
(
table
->
pos_in_table_list
&&
(
subq
=
table
->
pos_in_table_list
->
jtbm_subselect
))
{
return
subq
->
unit
->
first_select
()
->
select_number
;
}
return
0
;
/* Not a merged semi-join */
}
bool
access_from_tables_is_allowed
(
table_map
used_tables
,
bool
access_from_tables_is_allowed
(
table_map
used_tables
,
table_map
sjm_lookup_tables
)
table_map
sjm_lookup_tables
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment