Invalid plan and wrong result set for Q20 from DBT3 benchmark set
| Affects | Status | Importance | Assigned to | Milestone | |
|---|---|---|---|---|---|
| MariaDB |
Fix Released
|
Critical
|
Sergey Petrunia | ||
Bug Description
The query Q20 from DBT3 query set returns an empty result set for an InnoDB database of scale 10 in mariadb5.3.0.
The problem can be reproduced on a debug build (and a release build as well) with the following commands:
use dbt3sf10 [DBT3 of scale 10 created for InnoDB]
set optimizer_
set optimizer_
set optimizer_
select sql_calc_found_rows
s_name, s_address
from supplier, nation
where s_suppkey in (select ps_suppkey from partsupp
and s_nationkey = n_nationkey
and n_name = 'CANADA'
order by s_name
limit 10;
EXPLAIN shows that the execution plan is invalid, because it uses an outer reference when building a
materialized table.
+----+-
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-
| 1 | PRIMARY | supplier | ALL | PRIMARY,
| 1 | PRIMARY | nation | eq_ref | PRIMARY | PRIMARY | 4 | dbt3sf10.
| 1 | PRIMARY | <subquery2> | eq_ref | distinct_key | distinct_key | 4 | func | 1 | |
| 2 | SUBQUERY | part | ALL | PRIMARY | NULL | NULL | NULL | 1996969 | Using where |
| 2 | SUBQUERY | partsupp | eq_ref | PRIMARY,
| 4 | DEPENDENT SUBQUERY | lineitem | ref | i_l_shipdate,
+----+-
On my computer the bug is not reproducible at every execution. Sometimes the optimizer produces a valid plan that uses index i_ps_partkey and returns a correct result.
+----+-
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-
| 1 | PRIMARY | nation | ALL | PRIMARY | NULL | NULL | NULL | 25 | Using where; Using temporary; Using filesort |
| 1 | PRIMARY | supplier | ref | PRIMARY,
| 1 | PRIMARY | <subquery2> | eq_ref | distinct_key | distinct_key | 4 | func | 1 | |
| 2 | SUBQUERY | part | ALL | PRIMARY | NULL | NULL | NULL | 2001943 | Using where |
| 2 | SUBQUERY | partsupp | ref | PRIMARY,
| 4 | DEPENDENT SUBQUERY | lineitem | ref | i_l_shipdate,
+----+-
| Changed in maria: | |
| importance: | Undecided → Critical |
| assignee: | nobody → Sergey Petrunia (sergefp) |
| milestone: | none → 5.3 |
| summary: |
- Invalid plan abd wrong result set for Q20 from DBT3 benchmark set + Invalid plan and wrong result set for Q20 from DBT3 benchmark set |
| Changed in maria: | |
| status: | New → Fix Committed |
| Changed in maria: | |
| status: | Fix Committed → Fix Released |

Here's a way to reliably get the wrong query plan:
Use this query (note the added IGNORE INDEX clause):
explain select sql_calc_found_rows s_name, s_address
where ps_partkey in (select p_partkey from part
where p_name like 'forest%')
and ps_availqty > (select 0.5 * sum(l_quantity)
from lineitem
where l_partkey = ps_partkey and
l_ suppkey = ps_suppkey and
l_ shipdate >= date('1994-01-01')
and l_shipdate < date('1994-01-01') + interval '1' year
)
from
supplier, nation
where
s_suppkey in (select ps_suppkey from partsupp ignore index (i_ps_partkey)
)
and s_nationkey = n_nationkey and n_name = 'CANADA'
order by s_name limit 10;
In debugger: when best_access_path() is called with idx == 0 && !strcmp( s->table- >alias- >Ptr, "nation")
then at the end of the function do:
set best=100000
set records=25000