[MDEV-591] LP:927458 - The optimizer does not use ref access to the tables of a dependent subquery if ref is built over outer fields. Created: 2012-02-06  Updated: 2022-09-08

Status: Open
Project: MariaDB Server
Component/s: Optimizer
Affects Version/s: 5.3.12, 5.5, 10.0, 10.1
Fix Version/s: 10.1

Type: Bug Priority: Minor
Reporter: Igor Babaev Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: Launchpad, verified

Attachments: XML File LPexportBug927458.xml    

 Description   

This is a performance issue.

Let's create and populate tables t1, t2,t3 with the following commands:

CREATE TABLE t1 (
  pk int NOT NULL,
  col_int_nokey INT NOT NULL,
  col_int_key INT NOT NULL,
  PRIMARY KEY (pk),
  KEY col_int_key (col_int_key)
) ENGINE=MyISAM;
 
INSERT INTO t1 VALUES
(1,4,0),
(2,6,8),
(3,3,1),
(7,2,6),
(8,9,1),
(9,3,6),
(10,8,2),
(11,1,4),
(12,8,8),
(13,8,4),
(14,5,4);
 
CREATE TABLE t2 (
  pk int NOT NULL,
  col_int_nokey int NOT NULL,
  col_int_key int NOT NULL,
  PRIMARY KEY (pk),
  KEY col_int_key (col_int_key)
) ENGINE=MyISAM;
 
INSERT INTO t2 VALUES (10,8,7);
 
CREATE TABLE t3
SELECT grandparent1.col_int_nokey AS g1
FROM t1 AS grandparent1
WHERE (grandparent1.col_int_nokey, grandparent1.col_int_key) IN
   (SELECT parent1.col_int_key AS p1,
           parent1.col_int_key AS p2
    FROM t1 AS parent1
      LEFT JOIN t2 AS parent2
      ON parent1.col_int_nokey = parent2.col_int_key
    )
  AND grandparent1.col_int_key <> 3
;

Then for the query

SELECT * FROM t3
WHERE g1 NOT IN
   (SELECT grandparent1.col_int_nokey AS g1
    FROM t1 AS grandparent1
    WHERE (grandparent1.col_int_nokey, grandparent1.col_int_key) IN
       (SELECT parent1.col_int_key AS p1,
               parent1.col_int_key AS p2
        FROM t1 AS parent1
        LEFT JOIN t2 AS parent2
        ON parent1.col_int_nokey = parent2.col_int_key
        )
      AND grandparent1.col_int_key <> 3
);

mysql-5.6 chooses the plan:

+----+--------------------+--------------+-------+---------------+-------------+---------+------+------+-----------------------------------------------------------------+
| id | select_type        | table        | type  | possible_keys | key         | key_len | ref  | rows | Extra                                                           |
+----+--------------------+--------------+-------+---------------+-------------+---------+------+------+-----------------------------------------------------------------+
|  1 | PRIMARY            | t3           | ALL   | NULL          | NULL        | NULL    | NULL |    1 | Using where                                                     |
|  2 | DEPENDENT SUBQUERY | parent1      | ref   | col_int_key   | col_int_key | 4       | func |    2 | Using index condition; Start temporary                          |
|  2 | DEPENDENT SUBQUERY | parent2      | index | col_int_key   | col_int_key | 4       | NULL |    1 | Using where; Using index; Using join buffer (Block Nested Loop) |
|  2 | DEPENDENT SUBQUERY | grandparent1 | ref   | col_int_key   | col_int_key | 4       | func |    2 | Using index condition; Using where; End temporary               |
+----+--------------------+--------------+-------+---------------+-------------+---------+------+------+-----------------------------------------------------------------+
4 rows in set (0.03 sec)

while maria db-5.3 chooses the plan:

+----+--------------------+--------------+--------+---------------+-------------+---------+----------------------------+------+----------------------------------------------------------------+
| id | select_type        | table        | type   | possible_keys | key         | key_len | ref                        | rows | Extra                                                          |
+----+--------------------+--------------+--------+---------------+-------------+---------+----------------------------+------+----------------------------------------------------------------+
|  1 | PRIMARY            | t3           | system | NULL          | NULL        | NULL    | NULL                       |    1 |                                                                |
|  2 | DEPENDENT SUBQUERY | parent1      | ALL    | col_int_key   | NULL        | NULL    | NULL                       |   11 | Start temporary                                                |
|  2 | DEPENDENT SUBQUERY | parent2      | ref    | col_int_key   | col_int_key | 4       | test.parent1.col_int_nokey |    2 | Using index                                                    |
|  2 | DEPENDENT SUBQUERY | grandparent1 | ALL    | col_int_key   | NULL        | NULL    | NULL                       |   11 | Using where; End temporary; Using join buffer (flat, BNL join) |
+----+--------------------+--------------+--------+---------------+-------------+---------+----------------------------+------+----------------------------------------------------------------+

once the materialization flag of the optimizer switch is set to 'off'.

The first plan looks more efficient as table parent1 is accessed with an index look-up.

After an execution of the query in mysql-5.6 we have the following values of the read handler counters:

mysql> show status like '%Handler_read%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Handler_read_first    | 2     |
| Handler_read_key      | 4     |
| Handler_read_last     | 0     |
| Handler_read_next     | 4     |
| Handler_read_prev     | 0     |
| Handler_read_rnd      | 0     |
| Handler_read_rnd_next | 2     |
+-----------------------+-------+

while after an execution of the query in mariadb-5.3 we have:

MariaDB [test]> show status like '%Handler_read%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| Handler_read_first       | 0     |
| Handler_read_key         | 12    |
| Handler_read_next        | 0     |
| Handler_read_prev        | 0     |
| Handler_read_rnd         | 0     |
| Handler_read_rnd_deleted | 0     |
| Handler_read_rnd_next    | 22    |
+--------------------------+-------+



 Comments   
Comment by Elena Stepanova [ 2012-03-21 ]

Re: The optimizer does not use ref access to the tables of a dependent subquery if ref is built over outer fields.
Also filed in JIRA as MDEV-195

Comment by Rasmus Johansson (Inactive) [ 2012-03-29 ]

Launchpad bug id: 927458

Generated at Thu Feb 08 06:29:53 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.