[MDEV-4144] simple subquery causes full scan instead of range scan Created: 2013-02-06 Updated: 2013-04-02 Resolved: 2013-03-29 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | None |
| Affects Version/s: | 10.0.0, 5.5.29, 5.3.12 |
| Fix Version/s: | 10.0.2, 5.5.31, 5.3.13 |
| Type: | Bug | Priority: | Major |
| Reporter: | Patryk Pomykalski | Assignee: | Timour Katchaounov (Inactive) |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | optimizer | ||
| Description |
|
Test case:
output on mariadb (tested 5.3.5, 5.5.28, 5.5.29 and 10.0.0):
output on mysql (tested 5.0 and 5.1):
|
| Comments |
| Comment by Patryk Pomykalski [ 2013-02-06 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
forgot about explains: mariadb: (test) > explain SELECT x FROM t WHERE id > (SELECT MAX(id) - 1000 FROM t) ORDER BY x DESC LIMIT 1;
-----
----- mysql 5.1:
---
--- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Patryk Pomykalski [ 2013-02-06 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Mysql 5.5.30 works ok too: mysql [localhost] {msandbox} (test) > explain SELECT x FROM t WHERE id > (SELECT MAX(id) - 1000 FROM t) ORDER BY x LIMIT 1;
---
--- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2013-02-06 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Reproducible as described, with a bigger table as well (I went up to ~800K rows) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Patryk Pomykalski [ 2013-02-15 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
debugging... In get_mm_tree the subquery is considered expensive (not optimized). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Patryk Pomykalski [ 2013-02-15 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I'm not sure if this is a proper solution, but it works. Some query plans change. === modified file 'sql/item_subselect.cc' + if (cur_join->table_count == cur_join->const_tables) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2013-02-19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Agree.. The subquery is considered expensive, and range optimizer doesn't consider the "id > (SELECT ...)" predicate. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2013-02-19 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
What is weird, is why is this subquery considered expensive. The code in item_subselect.cc: Item_subselect::is_expensive() looks as if it was written to be able to distinguish between the expensive and in-expensive subqueries. Yet, debugging shows that execution in Item_subselect::is_expensive() returns here: /* If a subquery is not optimized we cannot estimate its cost. */ I'm wondering whether Patryk's addition may hit the subqueries that are not-yet-optimized (Do those subqueries may have cur_join->table_count == cur_join->const_tables?). Will discuss with Timour (his code). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Patryk Pomykalski [ 2013-03-27 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There's actually 'optimized' flag in join so maybe it should be something like this: — sql/item_subselect.cc 2013-03-17 10:41:25 +0000 /* If a subquery is not optimized we cannot estimate its cost. */
if (sl->first_inner_unit()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Timour Katchaounov (Inactive) [ 2013-03-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Patryk, you are very close to the solution, however JOIN::optimized is set in the very beginning of JOIN::optimize. There are much more extensive flags that describe the state of a query plan in a development branch of a 10.0 feature, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Timour Katchaounov (Inactive) [ 2013-03-29 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Pushed to 5.5.31 |