Bug #22930 Wrong EXPLAIN output for query with subquery
Submitted: 3 Oct 2006 12:41 Modified: 24 Jan 2007 23:40
Reporter: Sergey Petrunya Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:5.1-bk OS:
Assigned to: Assigned Account CPU Architecture:Any
Tags: explain, subquery, subselect

[3 Oct 2006 12:41] Sergey Petrunya
Description:
EXPLAIN for query with subquery can show incorrect data - the displayed query plan  is not valid for the query and it does not match actual query execution (in which there seem to be no errors).

How to repeat:
Run:

create table ten(a int);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

create table t1 (a int not null, b int not null, c int not null);
insert into t1 select A.a+10*(B.a+10 * C.a)) from ten A, ten B, ten C;

create table tpk(a int, b int, c int, primary key(a));
insert into tpk select * from t;

mysql> explain  select * from t1 where t1.b in (select a from tpk where tpk.c=t1.c);
+----+--------------------+-------+-----------------+---------------+---------+---------+------+------+--------------------------+
| id | select_type        | table | type            | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+--------------------+-------+-----------------+---------------+---------+---------+------+------+--------------------------+
|  1 | PRIMARY            | t1    | ALL             | NULL          | NULL   NULL    | NULL | 1000 | Using where              | 
|  2 | DEPENDENT SUBQUERY | tpk   | unique_subquery | PRIMARY       | PRIMARY | 4       | func |    1 | Using index; Using where | 
+----+--------------------+-------+-----------------+---------------+---------+---------+------+------+--------------------------+
2 rows in set (1.30 sec)

The EXPLAIN shows that table tpk will be accessed "Using index", which is not possible: we will need full table rows as well because we'll need value of tpk.c.

Suggested fix:
It is only EXPLAIN output that is wrong. Actually 'Using index' is not used for table tpk. This can be proven by setting breakpoint and arriving at this stack trace:
(gdb) wher
  #0  _mi_read_static_record (info=0x8fa51b8, pos=13, record=0x8fa49c8 "ù") at mi_statrec.c:176
  #1  0x084eb478 in mi_rkey (info=0x8fa51b8, buf=0x8fa49c8 "ù", inx=0, key=0x8fa7c18 "\001", key_len=4, search_flag=HA_READ_KEY_EXACT) at mi_rkey.c:151
  #2  0x084e16ad in ha_myisam::index_read (this=0x8fa48c0, buf=0x8fa49c8 "ù", key=0x8fa7c18 "\001", key_len=4, find_flag=HA_READ_KEY_EXACT) at ha_myisam.cc:1211
  #3  0x082067d9 in subselect_uniquesubquery_engine::exec (this=0x8fac340) at item_subselect.cc:1672
  #4  0x082024ba in Item_subselect::exec (this=0x8f9d360) at item_subselect.cc:242
  #5  0x08203d94 in Item_in_subselect::val_bool (this=0x8f9d360) at item_subselect.cc:772
  #6  0x081b1400 in Item::val_bool_result (this=0x8f9d360) at item.h:680
  #7  0x081d8487 in Item_in_optimizer::val_int (this=0x8fa7008) at item_cmpfunc.cc:838
  #8  0x082be264 in evaluate_join_record (join=0x8f9d4b8, join_tab=0x8fa7648, error=0, report_error=0x8f73b4c "") at sql_select.cc:10289
  #9  0x082be142 in sub_select (join=0x8f9d4b8, join_tab=0x8fa7648, end_of_records=false) at sql_select.cc:10248
  #10 0x082bdc94 in do_select (join=0x8f9d4b8, fields=0x8f733dc, table=0x0, procedure=0x0) at sql_select.cc:10005
  #11 0x082ab9ce in JOIN::exec (this=0x8f9d4b8) at sql_select.cc:1843
  #12 0x082abf4d in mysql_select (thd=0x8f73070, rref_pointer_array=0x8f73478, tables=0x8f9c880, wild_num=1, fields=@0x8f733dc, conds=0x8f9d360, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2147764736, result=0x8f9d4a8, unit=0x8f73118, select_lex=0x8f73350) at sql_select.cc:2005
  #13 0x082a66fa in handle_select (thd=0x8f73070, lex=0x8f730b0, result=0x8f9d4a8, setup_tables_done_option=0) at sql_select.cc:242
  #14 0x08269c27 in execute_sqlcom_select (thd=0x8f73070, all_tables=0x8f9c880) at sql_parse.cc:5262
  #15 0x08261d69 in mysql_execute_command (thd=0x8f73070) at sql_parse.cc:2628
  #16 0x0826b8f1 in mysql_parse (thd=0x8f73070, inBuf=0x8f9c740 "select * from t1 where t1.b in (select a from tpk where tpk.c=t1.c)", length=67) at sql_parse.cc:6080
  #17 0x0825fdf6 in dispatch_command (command=COM_QUERY, thd=0x8f73070, packet=0x8f946e1 "", packet_length=68) at sql_parse.cc:1828
[24 Jan 2007 23:40] Sergey Petrunya
Fixed by fix for BUG#24127