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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
a2209050
Commit
a2209050
authored
Apr 02, 2015
by
Oleksandr Byelkin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-7833:ANALYZE FORMAT=JSON and Range checked for each record
parent
7f613ebd
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
234 additions
and
13 deletions
+234
-13
mysql-test/r/analyze_format_json.result
mysql-test/r/analyze_format_json.result
+64
-0
mysql-test/t/analyze_format_json.test
mysql-test/t/analyze_format_json.test
+30
-0
sql/sql_explain.cc
sql/sql_explain.cc
+101
-5
sql/sql_explain.h
sql/sql_explain.h
+19
-1
sql/sql_select.cc
sql/sql_select.cc
+14
-6
sql/sql_select.h
sql/sql_select.h
+6
-1
No files found.
mysql-test/r/analyze_format_json.result
View file @
a2209050
...
...
@@ -341,3 +341,67 @@ ANALYZE
}
}
drop table t1, t3, t2;
#
# MDEV-7833:ANALYZE FORMAT=JSON and Range checked for each record
#
create table t3(a int);
insert into t3 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t4(a int);
insert into t4 select A.a + B.a* 10 + C.a * 100 from t3 A, t3 B, t3 C;
create table t1 (lb1 int, rb1 int, lb2 int, rb2 int, c1 int, c2 int);
insert into t1 values (1,2,10,20,15,15);
insert into t1 values (3,5,10,20,15,15);
insert into t1 values (10,20,10,20,15,15);
insert into t1 values (10,20,1,2,15,15);
insert into t1 values (10,20,10,20,1,3);
create table t2 (key1 int, key2 int, key3 int, key4 int, col1 int,
key(key1), key(key2), key(key3), key(key4));
insert into t2 select a,a,a,a,a from t3;
insert into t2 select 15,15,15,15,15 from t4;
analyze format=json
select * from t1, t2 where (t2.key1 between t1.lb1 and t1.rb1) and
(t2.key2 between t1.lb2 and t1.rb2) and
(t2.key3=t1.c1 OR t2.key4=t1.c2);
ANALYZE
{
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
"table_name": "t1",
"access_type": "ALL",
"r_loops": 1,
"rows": 5,
"r_rows": 5,
"r_total_time_ms": "REPLACED",
"filtered": 100,
"r_filtered": 100
},
"range-checked-for-each-record": {
"keys": ["key1", "key2", "key3", "key4"],
"r_keys": {
"full_scan": 1,
"index_merge": 1,
"range": {
"key1": 2,
"key2": 1,
"key3": 0,
"key4": 0
}
},
"table": {
"table_name": "t2",
"access_type": "ALL",
"possible_keys": ["key1", "key2", "key3", "key4"],
"r_loops": 5,
"rows": 1010,
"r_rows": 203.8,
"r_total_time_ms": "REPLACED",
"filtered": 100,
"r_filtered": 98.135
}
}
}
}
drop table t1,t2,t3,t4;
mysql-test/t/analyze_format_json.test
View file @
a2209050
...
...
@@ -104,3 +104,33 @@ analyze format=json
delete
from
t1
where
pk
<
10
and
b
>
4
;
drop
table
t1
,
t3
,
t2
;
--
echo
#
--
echo
# MDEV-7833:ANALYZE FORMAT=JSON and Range checked for each record
--
echo
#
create
table
t3
(
a
int
);
insert
into
t3
values
(
0
),(
1
),(
2
),(
3
),(
4
),(
5
),(
6
),(
7
),(
8
),(
9
);
create
table
t4
(
a
int
);
insert
into
t4
select
A
.
a
+
B
.
a
*
10
+
C
.
a
*
100
from
t3
A
,
t3
B
,
t3
C
;
create
table
t1
(
lb1
int
,
rb1
int
,
lb2
int
,
rb2
int
,
c1
int
,
c2
int
);
insert
into
t1
values
(
1
,
2
,
10
,
20
,
15
,
15
);
insert
into
t1
values
(
3
,
5
,
10
,
20
,
15
,
15
);
insert
into
t1
values
(
10
,
20
,
10
,
20
,
15
,
15
);
insert
into
t1
values
(
10
,
20
,
1
,
2
,
15
,
15
);
insert
into
t1
values
(
10
,
20
,
10
,
20
,
1
,
3
);
create
table
t2
(
key1
int
,
key2
int
,
key3
int
,
key4
int
,
col1
int
,
key
(
key1
),
key
(
key2
),
key
(
key3
),
key
(
key4
));
insert
into
t2
select
a
,
a
,
a
,
a
,
a
from
t3
;
insert
into
t2
select
15
,
15
,
15
,
15
,
15
from
t4
;
--
replace_regex
/
"r_total_time_ms"
:
[
0
-
9
]
*
[
.
]
?
[
0
-
9
]
*/
"r_total_time_ms"
:
"REPLACED"
/
analyze
format
=
json
select
*
from
t1
,
t2
where
(
t2
.
key1
between
t1
.
lb1
and
t1
.
rb1
)
and
(
t2
.
key2
between
t1
.
lb2
and
t1
.
rb2
)
and
(
t2
.
key3
=
t1
.
c1
OR
t2
.
key4
=
t1
.
c2
);
drop
table
t1
,
t2
,
t3
,
t4
;
sql/sql_explain.cc
View file @
a2209050
...
...
@@ -22,6 +22,7 @@
#include "sql_priv.h"
#include "sql_select.h"
#include "my_json_writer.h"
#include "opt_range.h"
const
char
*
STR_DELETING_ALL_ROWS
=
"Deleting all rows"
;
const
char
*
STR_IMPOSSIBLE_WHERE
=
"Impossible WHERE"
;
...
...
@@ -1076,15 +1077,26 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai
}
bool
String_list
::
append_str
(
MEM_ROOT
*
mem_root
,
const
char
*
str
)
/**
Adds copy of the string to the list
@param mem_root where to allocate string
@param str string to copy and add
@return
NULL - out of memory error
poiner on allocated copy of the string
*/
const
char
*
String_list
::
append_str
(
MEM_ROOT
*
mem_root
,
const
char
*
str
)
{
size_t
len
=
strlen
(
str
);
char
*
cp
;
if
(
!
(
cp
=
(
char
*
)
alloc_root
(
mem_root
,
len
+
1
)))
return
1
;
return
NULL
;
memcpy
(
cp
,
str
,
len
+
1
);
push_back
(
cp
);
return
0
;
return
cp
;
}
...
...
@@ -1207,8 +1219,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
if
(
range_checked_fer
)
{
writer
->
add_member
(
"range-checked-for-each-record"
).
start_object
();
add_json_keyset
(
writer
,
"keys"
,
&
possible_keys
);
range_checked_fer
->
print_json
(
writer
,
is_analyze
);
}
if
(
full_scan_on_null_key
)
...
...
@@ -1986,3 +1997,88 @@ void create_explain_query_if_not_exists(LEX *lex, MEM_ROOT *mem_root)
create_explain_query
(
lex
,
mem_root
);
}
/**
Build arrays for collectiong keys statistics, sdd possible key names
to the list and name array
@param alloc MEM_ROOT to put data in
@param list list of possible key names to fill
@param table table of the keys
@patam possible_keys possible keys map
@retval 0 - OK
@retval 1 - Error
*/
int
Explain_range_checked_fer
::
append_possible_keys_stat
(
MEM_ROOT
*
alloc
,
TABLE
*
table
,
key_map
possible_keys
)
{
uint
j
;
multi_alloc_root
(
alloc
,
&
keys_stat
,
sizeof
(
ha_rows
)
*
table
->
s
->
keys
,
&
keys_stat_names
,
sizeof
(
char
*
)
*
table
->
s
->
keys
,
NULL
);
if
((
!
keys_stat
)
||
(
!
keys_stat_names
))
{
keys_stat
=
NULL
;
keys_stat_names
=
NULL
;
return
1
;
}
keys_map
=
possible_keys
;
keys
=
table
->
s
->
keys
;
bzero
(
keys_stat
,
sizeof
(
ha_rows
)
*
table
->
s
->
keys
);
for
(
j
=
0
;
j
<
table
->
s
->
keys
;
j
++
)
{
if
(
possible_keys
.
is_set
(
j
))
keys_stat_names
[
j
]
=
key_set
.
append_str
(
alloc
,
table
->
key_info
[
j
].
name
);
else
keys_stat_names
[
j
]
=
NULL
;
}
return
0
;
}
void
Explain_range_checked_fer
::
collect_data
(
QUICK_SELECT_I
*
quick
)
{
if
(
quick
)
{
if
(
quick
->
index
==
MAX_KEY
)
index_merge
++
;
else
{
DBUG_ASSERT
(
quick
->
index
<
keys
);
DBUG_ASSERT
(
keys_stat
);
DBUG_ASSERT
(
keys_stat_names
);
DBUG_ASSERT
(
keys_stat_names
[
quick
->
index
]);
keys_stat
[
quick
->
index
]
++
;
}
}
else
full_scan
++
;
}
void
Explain_range_checked_fer
::
print_json
(
Json_writer
*
writer
,
bool
is_analyze
)
{
writer
->
add_member
(
"range-checked-for-each-record"
).
start_object
();
add_json_keyset
(
writer
,
"keys"
,
&
key_set
);
if
(
is_analyze
)
{
writer
->
add_member
(
"r_keys"
).
start_object
();
writer
->
add_member
(
"full_scan"
).
add_ll
(
full_scan
);
writer
->
add_member
(
"index_merge"
).
add_ll
(
index_merge
);
if
(
keys_stat
)
{
writer
->
add_member
(
"range"
).
start_object
();
for
(
uint
i
=
0
;
i
<
keys
;
i
++
)
{
if
(
keys_stat_names
[
i
])
{
writer
->
add_member
(
keys_stat_names
[
i
]).
add_ll
(
keys_stat
[
i
]);
}
}
writer
->
end_object
();
}
writer
->
end_object
();
}
}
sql/sql_explain.h
View file @
a2209050
...
...
@@ -54,7 +54,7 @@ it into the slow query log.
class
String_list
:
public
List
<
char
>
{
public:
bool
append_str
(
MEM_ROOT
*
mem_root
,
const
char
*
str
);
const
char
*
append_str
(
MEM_ROOT
*
mem_root
,
const
char
*
str
);
};
class
Json_writer
;
...
...
@@ -622,11 +622,29 @@ class Explain_quick_select : public Sql_alloc
It's a set of keys, tabular explain prints hex bitmap, json prints key names.
*/
typedef
const
char
*
NAME
;
class
Explain_range_checked_fer
:
public
Sql_alloc
{
public:
String_list
key_set
;
key_map
keys_map
;
private:
ha_rows
full_scan
,
index_merge
;
ha_rows
*
keys_stat
;
NAME
*
keys_stat_names
;
uint
keys
;
public:
Explain_range_checked_fer
()
:
Sql_alloc
(),
full_scan
(
0
),
index_merge
(
0
),
keys_stat
(
0
),
keys_stat_names
(
0
),
keys
(
0
)
{}
int
append_possible_keys_stat
(
MEM_ROOT
*
alloc
,
TABLE
*
table
,
key_map
possible_keys
);
void
collect_data
(
QUICK_SELECT_I
*
quick
);
void
print_json
(
Json_writer
*
writer
,
bool
is_analyze
);
};
/*
...
...
sql/sql_select.cc
View file @
a2209050
...
...
@@ -11398,6 +11398,7 @@ void JOIN_TAB::cleanup()
table->reginfo.join_tab= 0;
}
end_read_record(&read_record);
explain_plan= NULL;
DBUG_VOID_RETURN;
}
...
...
@@ -18762,9 +18763,13 @@ test_if_quick_select(JOIN_TAB *tab)
delete tab->select->quick;
tab->select->quick=0;
return tab->select->test_quick_select(tab->join->thd, tab->keys,
(table_map) 0, HA_POS_ERROR, 0,
FALSE, /*remove where parts*/FALSE);
int res= tab->select->test_quick_select(tab->join->thd, tab->keys,
(table_map) 0, HA_POS_ERROR, 0,
FALSE, /*remove where parts*/FALSE);
if (tab->explain_plan && tab->explain_plan->range_checked_fer)
tab->explain_plan->range_checked_fer->collect_data(tab->select->quick);
return res;
}
...
...
@@ -23387,6 +23392,7 @@ int append_possible_keys(MEM_ROOT *alloc, String_list &list, TABLE *table,
return 0;
}
/*
TODO: this function is only applicable for the first non-const optimization
join tab.
...
...
@@ -23427,6 +23433,8 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
quick_type= -1;
QUICK_SELECT_I *quick= NULL;
explain_plan= eta;
eta->key.clear();
eta->quick_info= NULL;
...
...
@@ -23690,9 +23698,9 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, table_map prefix_tab
{
eta->push_extra(ET_RANGE_CHECKED_FOR_EACH_RECORD);
eta->range_checked_fer= new (thd->mem_root) Explain_range_checked_fer;
eta->range_checked_fer->keys_map= tab->keys;
append_possible_keys(thd->mem_root, eta->range_checked_fer->key_set,
table, tab->keys);
if (eta->range_checked_fer)
eta->range_checked_fer->
append_possible_keys_stat(thd->mem_root,
table, tab->keys);
}
else if (tab->select->cond ||
(tab->cache_select && tab->cache_select->cond))
...
...
sql/sql_select.h
View file @
a2209050
...
...
@@ -362,7 +362,12 @@ typedef struct st_join_table {
SJ_TMP_TABLE
*
check_weed_out_table
;
/* for EXPLAIN only: */
SJ_TMP_TABLE
*
first_weedout_table
;
/**
reference to saved plan and execution statistics
*/
Explain_table_access
*
explain_plan
;
/*
If set, means we should stop join enumeration after we've got the first
match and return to the specified join tab. May point to
...
...
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