[MDEV-8359] WHERE condition referring to inner table of left join can be sargable Created: 2015-06-23 Updated: 2023-03-24 |
|
| Status: | Stalled |
| Project: | MariaDB Server |
| Component/s: | Optimizer |
| Fix Version/s: | 11.2 |
| Type: | Task | Priority: | Major |
| Reporter: | VAROQUI Stephane | Assignee: | Sergei Petrunia |
| Resolution: | Unresolved | Votes: | 2 |
| Labels: | optimizer, outer-join | ||
| Issue Links: |
|
||||||||
| Sprint: | 10.2.4-4, 10.2.4-1, 10.2.4-2 | ||||||||
| Description |
|
Some ERP generate that type of queries
The full index scan on primary table is not necessary if const on joined table is not NULL. Rewriting the query is hard to be done in the application because it may happen that the application is doing a lookup for NULL on left joined table indeed query rewriting change the lookup to const or range in case the second condition is not null and propagated to the upper table
|
| Comments |
| Comment by Sergei Petrunia [ 2015-06-23 ] | ||||||||||||
|
So, the second query has
which allows the optimizer to read only rows with E_relance.id_demande=88224, i.e use ref access. The first query is:
The question is, can we satisfy the first query by just looking at rows with E_relance.id_demande=88224 ? | ||||||||||||
| Comment by Sergei Petrunia [ 2015-06-23 ] | ||||||||||||
|
The answer is "YES", one can infer that by following this logic: Suppose we read a row from E_relance, such that (E_relance.id_demande=88224)= FALSE 2. E_action has a match. ON expression then guarantees that (E_action.id_demande = 88224)= FALSE, which means that the WHERE condition will evaluate to false. Now, the question is, how can one generalize this logic to a rule that could be | ||||||||||||
| Comment by VAROQUI Stephane [ 2015-06-23 ] | ||||||||||||
|
The condition can be push up if left join and const is not null and fully push up for inner join | ||||||||||||
| Comment by Sergei Petrunia [ 2015-06-23 ] | ||||||||||||
|
The above logic can only be applied in a limited number of cases: First, the OR must be a two-way OR. If the WHERE expression was
then it would be possible that
we would still need to scan the whole table E_relance to check unknown_cond for all rows. What if the constants in the WHERE were not the same? Consider
Suppose we read a row from E_relance, such that (E_relance.id_demande=1)= FALSE. So, we'll need to scan rows with E_relance.id_demande IN (1,2). | ||||||||||||
| Comment by Sergei Petrunia [ 2015-06-23 ] | ||||||||||||
|
Attempt to generalize #1:
Need to think of:
| ||||||||||||
| Comment by Sergei Petrunia [ 2015-06-24 ] | ||||||||||||
|
Checked PostgreSQL:
Note the Seq Scan elements. They dont have the optimization that we're talking about here. | ||||||||||||
| Comment by Sergei Petrunia [ 2016-10-13 ] | ||||||||||||
|
Re the *Attempt to generalize #1* : Here's a justification why it is correct:
The question is, can we replace cond(t2.col) with cond(t1.col)? (if not replace altogether, at least do it for the purpose of doing range analysis on table t1) Let's consider how the WHERE clause is computed for various kinds of (t1.row, t2.row) record combinations.
Consider a row combination of type #1. It has t1.col=t2.col, which means the value of cond(t1.col) will be the same as the value cond(t2.col). Consider a row combination of type #2. t2.col is a NULL, cond(NULL) is not the same as cond(t1.col). when cond(t2.col) is at top-level of the WHERE clause, and is NULL-rejecting wrt t2.col, it will evaluate to FALSE, and cause the entire WHERE to evaluate to FALSE.
If the latter happens, we will get extra rows. However, this is not an issue if we just use this substitution for the purpose of constructing range/index_merge As for nested outer joins: We don't care about the nesting. t2.col must be either an NULL-complemented row, or the row must have t2.col=t1.col. | ||||||||||||
| Comment by Sergei Petrunia [ 2016-10-13 ] | ||||||||||||
|
A basic example to play with:
Debugging this, one can see a difficulty in the implementation: | ||||||||||||
| Comment by Sergei Petrunia [ 2016-10-13 ] | ||||||||||||
|
http://lists.askmonty.org/pipermail/commits/2016-October/009987.html elenst, I would like a test pass for this. Need outer joins
| ||||||||||||
| Comment by Sergei Petrunia [ 2016-10-14 ] | ||||||||||||
|
This fix doesn't help with MDEV-10946. | ||||||||||||
| Comment by VAROQUI Stephane [ 2016-10-14 ] | ||||||||||||
|
Miam Miam! Thanks for this fix | ||||||||||||
| Comment by Elena Stepanova [ 2016-10-31 ] | ||||||||||||
I've run tests on the patch comparing to the vanilla tree, didn't get any problems which weren't there before the patch. Please go ahead and push, there will also be regular regression tests on the main tree. | ||||||||||||
| Comment by Sergei Petrunia [ 2016-11-15 ] | ||||||||||||
|
Igor, please review | ||||||||||||
| Comment by Sergei Petrunia [ 2017-01-27 ] | ||||||||||||
|
Re-assigning to me as the ball is on my side currently. |