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
3b6d9038
Commit
3b6d9038
authored
Oct 23, 2018
by
Sergei Petrunia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-17493: Partition pruning doesn't work for nested outer joins
Reuse the fix for MDEV-17518 here, too.
parent
03680a9b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
120 additions
and
61 deletions
+120
-61
mysql-test/main/partition_pruning.result
mysql-test/main/partition_pruning.result
+33
-0
mysql-test/main/partition_pruning.test
mysql-test/main/partition_pruning.test
+31
-0
sql/sql_select.cc
sql/sql_select.cc
+50
-59
sql/sql_select.h
sql/sql_select.h
+6
-2
No files found.
mysql-test/main/partition_pruning.result
View file @
3b6d9038
...
@@ -3484,3 +3484,36 @@ select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) O
...
@@ -3484,3 +3484,36 @@ select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) O
a b c d
a b c d
1 a b 1
1 a b 1
drop table t1;
drop table t1;
#
# MDEV-17493: Partition pruning doesn't work for nested outer joins
#
create table t0(a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1 (a int, b int, c int);
insert into t1 select a,a,a from t0;
create table t2 (a int, b int, c int);
insert into t2 select a,a,a from t0;
create table t3 (
part_id int,
a int
) partition by list (part_id) (
partition p0 values in (0),
partition p1 values in (1),
partition p2 values in (2),
partition p3 values in (3),
partition p4 values in (4)
);
insert into t3 select mod(a,5), a from t0;
explain partitions
select * from t1 left join t3 on (t1.a=t3.a and t3.part_id=3);
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 10
1 SIMPLE t3 p3 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
# The following should have partitions="p3", NOT p0,p1,p2,p3,p4:
explain partitions
select * from t1 left join (t3 join t2) on (t1.a=t3.a and t3.a=t2.b and t3.part_id=3);
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 10
1 SIMPLE t3 p3 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
1 SIMPLE t2 NULL ALL NULL NULL NULL NULL 10 Using where; Using join buffer (incremental, BNL join)
drop table t0,t1,t2,t3;
mysql-test/main/partition_pruning.test
View file @
3b6d9038
...
@@ -1535,4 +1535,35 @@ select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) O
...
@@ -1535,4 +1535,35 @@ select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) O
(
a
=
1
AND
b
>=
'a'
AND
(
c
=
'c'
OR
(
c
=
'd'
AND
d
=
2
))));
(
a
=
1
AND
b
>=
'a'
AND
(
c
=
'c'
OR
(
c
=
'd'
AND
d
=
2
))));
drop
table
t1
;
drop
table
t1
;
--
echo
#
--
echo
# MDEV-17493: Partition pruning doesn't work for nested outer joins
--
echo
#
create
table
t0
(
a
int
);
insert
into
t0
values
(
0
),(
1
),(
2
),(
3
),(
4
),(
5
),(
6
),(
7
),(
8
),(
9
);
create
table
t1
(
a
int
,
b
int
,
c
int
);
insert
into
t1
select
a
,
a
,
a
from
t0
;
create
table
t2
(
a
int
,
b
int
,
c
int
);
insert
into
t2
select
a
,
a
,
a
from
t0
;
create
table
t3
(
part_id
int
,
a
int
)
partition
by
list
(
part_id
)
(
partition
p0
values
in
(
0
),
partition
p1
values
in
(
1
),
partition
p2
values
in
(
2
),
partition
p3
values
in
(
3
),
partition
p4
values
in
(
4
)
);
insert
into
t3
select
mod
(
a
,
5
),
a
from
t0
;
explain
partitions
select
*
from
t1
left
join
t3
on
(
t1
.
a
=
t3
.
a
and
t3
.
part_id
=
3
);
--
echo
# The following should have partitions="p3", NOT p0,p1,p2,p3,p4:
explain
partitions
select
*
from
t1
left
join
(
t3
join
t2
)
on
(
t1
.
a
=
t3
.
a
and
t3
.
a
=
t2
.
b
and
t3
.
part_id
=
3
);
drop
table
t0
,
t1
,
t2
,
t3
;
sql/sql_select.cc
View file @
3b6d9038
...
@@ -292,6 +292,9 @@ static bool find_order_in_list(THD *, Ref_ptr_array, TABLE_LIST *, ORDER *,
...
@@ -292,6 +292,9 @@ static bool find_order_in_list(THD *, Ref_ptr_array, TABLE_LIST *, ORDER *,
static
double
table_cond_selectivity
(
JOIN
*
join
,
uint
idx
,
JOIN_TAB
*
s
,
static
double
table_cond_selectivity
(
JOIN
*
join
,
uint
idx
,
JOIN_TAB
*
s
,
table_map
rem_tables
);
table_map
rem_tables
);
void
set_postjoin_aggr_write_func
(
JOIN_TAB
*
tab
);
void
set_postjoin_aggr_write_func
(
JOIN_TAB
*
tab
);
static
Item
**
get_sargable_cond
(
JOIN
*
join
,
TABLE
*
table
);
#ifndef DBUG_OFF
#ifndef DBUG_OFF
/*
/*
...
@@ -1770,19 +1773,9 @@ JOIN::optimize_inner()
...
@@ -1770,19 +1773,9 @@ JOIN::optimize_inner()
List_iterator_fast
<
TABLE_LIST
>
li
(
select_lex
->
leaf_tables
);
List_iterator_fast
<
TABLE_LIST
>
li
(
select_lex
->
leaf_tables
);
while
((
tbl
=
li
++
))
while
((
tbl
=
li
++
))
{
{
/*
Item
**
prune_cond
=
get_sargable_cond
(
this
,
tbl
->
table
);
If tbl->embedding!=NULL that means that this table is in the inner
tbl
->
table
->
all_partitions_pruned_away
=
part of the nested outer join, and we can't do partition pruning
prune_partitions
(
thd
,
tbl
->
table
,
*
prune_cond
);
(TODO: check if this limitation can be lifted)
*/
if
(
!
tbl
->
embedding
||
(
tbl
->
embedding
&&
tbl
->
embedding
->
sj_on_expr
))
{
Item
*
prune_cond
=
tbl
->
on_expr
?
tbl
->
on_expr
:
conds
;
tbl
->
table
->
all_partitions_pruned_away
=
prune_partitions
(
thd
,
tbl
->
table
,
prune_cond
);
}
}
}
}
}
#endif
#endif
...
@@ -4334,6 +4327,47 @@ void mark_join_nest_as_const(JOIN *join,
...
@@ -4334,6 +4327,47 @@ void mark_join_nest_as_const(JOIN *join,
}
}
}
}
/*
@brief Get the condition that can be used to do range analysis/partition
pruning/etc
@detail
Figure out which condition we can use:
- For INNER JOIN, we use the WHERE,
- "t1 LEFT JOIN t2 ON ..." uses t2's ON expression
- "t1 LEFT JOIN (...) ON ..." uses the join nest's ON expression.
*/
static
Item
**
get_sargable_cond
(
JOIN
*
join
,
TABLE
*
table
)
{
Item
**
retval
;
if
(
table
->
pos_in_table_list
->
on_expr
)
{
/*
This is an inner table from a single-table LEFT JOIN, "t1 LEFT JOIN
t2 ON cond". Use the condition cond.
*/
retval
=
&
table
->
pos_in_table_list
->
on_expr
;
}
else
if
(
table
->
pos_in_table_list
->
embedding
&&
!
table
->
pos_in_table_list
->
embedding
->
sj_on_expr
)
{
/*
This is the inner side of a multi-table outer join. Use the
appropriate ON expression.
*/
retval
=
&
(
table
->
pos_in_table_list
->
embedding
->
on_expr
);
}
else
{
/* The table is not inner wrt some LEFT JOIN. Use the WHERE clause */
retval
=
&
join
->
conds
;
}
return
retval
;
}
/**
/**
Calculate the best possible join and initialize the join structure.
Calculate the best possible join and initialize the join structure.
...
@@ -4919,42 +4953,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
...
@@ -4919,42 +4953,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
SQL_SELECT
*
select
=
0
;
SQL_SELECT
*
select
=
0
;
if
(
!
s
->
const_keys
.
is_clear_all
())
if
(
!
s
->
const_keys
.
is_clear_all
())
{
{
Item
*
sargable_cond
;
Item
**
sargable_cond
=
get_sargable_cond
(
join
,
s
->
table
);
int
cond_source
;
/*
Figure out which condition we should use for range analysis. For
INNER JOIN, we use the WHERE, for inner side of LEFT JOIN we should
use the ON expression.
*/
if
(
*
s
->
on_expr_ref
)
{
/*
This is an inner table from a single-table LEFT JOIN, "t1 LEFT JOIN
t2 ON cond". Use the condition cond.
*/
cond_source
=
0
;
sargable_cond
=
*
s
->
on_expr_ref
;
}
else
if
(
s
->
table
->
pos_in_table_list
->
embedding
&&
!
s
->
table
->
pos_in_table_list
->
embedding
->
sj_on_expr
)
{
/*
This is the inner side of a multi-table outer join. Use the
appropriate ON expression.
*/
cond_source
=
1
;
sargable_cond
=
s
->
table
->
pos_in_table_list
->
embedding
->
on_expr
;
}
else
{
/* The table is not inner wrt some LEFT JOIN. Use the WHERE clause */
cond_source
=
2
;
sargable_cond
=
join
->
conds
;
}
select
=
make_select
(
s
->
table
,
found_const_table_map
,
select
=
make_select
(
s
->
table
,
found_const_table_map
,
found_const_table_map
,
found_const_table_map
,
sargable_cond
,
*
sargable_cond
,
(
SORT_INFO
*
)
0
,
(
SORT_INFO
*
)
0
,
1
,
&
error
);
1
,
&
error
);
if
(
!
select
)
if
(
!
select
)
...
@@ -4966,19 +4969,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
...
@@ -4966,19 +4969,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
Range analyzer might have modified the condition. Put it the new
Range analyzer might have modified the condition. Put it the new
condition to where we got it from.
condition to where we got it from.
*/
*/
switch
(
cond_source
)
{
*
sargable_cond
=
select
->
cond
;
case
0
:
*
s
->
on_expr_ref
=
select
->
cond
;
break
;
case
1
:
s
->
table
->
pos_in_table_list
->
embedding
->
on_expr
=
select
->
cond
;
break
;
case
2
:
join
->
conds
=
select
->
cond
;
break
;
default:
DBUG_ASSERT
(
0
);
}
s
->
quick
=
select
->
quick
;
s
->
quick
=
select
->
quick
;
s
->
needed_reg
=
select
->
needed_reg
;
s
->
needed_reg
=
select
->
needed_reg
;
...
...
sql/sql_select.h
View file @
3b6d9038
...
@@ -263,8 +263,12 @@ typedef struct st_join_table {
...
@@ -263,8 +263,12 @@ typedef struct st_join_table {
/*
/*
Pointer to the associated ON expression. on_expr_ref=!NULL except for
Pointer to the associated ON expression. on_expr_ref=!NULL except for
degenerate joins.
degenerate joins.
*on_expr_ref!=NULL for tables that are first inner tables within an outer
join.
Optimization phase: *on_expr_ref!=NULL for tables that are the single
tables on the inner side of the outer join (t1 LEFT JOIN t2 ON...)
Execution phase: *on_expr_ref!=NULL for tables that are first inner tables
within an outer join (which may have multiple tables)
*/
*/
Item
**
on_expr_ref
;
Item
**
on_expr_ref
;
COND_EQUAL
*
cond_equal
;
/**< multiple equalities for the on expression */
COND_EQUAL
*
cond_equal
;
/**< multiple equalities for the on expression */
...
...
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