子查询的外部查询非常慢(Mysql)

时间:2018-04-21 08:02:48

标签: mysql subquery

我有一个带有两级深度子查询的聚合查询。奇怪的是,这两个子查询运行速度可以接受,但外部查询速度慢得令人无法接受。

查询背后的基本思想是使用表来查找链接到键的所有元素,这些元素由其中一个元素查询选择。然后应将此结果集提供给外部查询,该查询将根据其自己的键/索引与其匹配。

这里包含所有输出和陈述:

我们从两个表格定义

开始
CREATE TABLE `table1` (
  `id1` int(11) NOT NULL DEFAULT '0',
  `id2` int(11) NOT NULL,
  `value` int(11) DEFAULT '0',
  PRIMARY KEY (`id1`,`id2`),
  KEY `k_id1` (`id1`),
  KEY `k_id2` (`id2`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1


CREATE TABLE `lookuptable1` (
  `id3` int(11) NOT NULL,
  `id4` int(11) NOT NULL,
  PRIMARY KEY (`id3`,`id4`),
  UNIQUE KEY `id4_idx` (`id4`),
  KEY `id3_idx` (`id3`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

带有子查询的内部子查询

SELECT lt1.id4
    FROM lookuptable1 lt1
    WHERE lt1.id3 = (SELECT pt1.id3
                    FROM lookuptable1 pt1
                    WHERE pt1.id4 = 5960)
+-----------+
|    id4    |
+-----------+
|      5960 |
|     17215 |
|   3625734 |
|   9312798 |
+-----------+
4 rows in set (0.00 sec)

如你所见:足够快。

但外部查询是坏瓶颈所在。 完整查询

SELECT
  t1.id1,
  sum(t1.value)
FROM table1 t1
WHERE t1.id2 = 3 AND t1.id1 IN
  (
    SELECT lt1.id4
    FROM lookuptable1 lt1
    WHERE lt1.id3 = (SELECT pt1.id3
                    FROM lookuptable1 pt1
                    WHERE pt1.id4 = 5960)
  );

+-----------+-----------------------+
|  id 1.    | sum(t1.value)         |
+-----------+-----------------------+
|   9312798 |                     0 |
+-----------+-----------------------+
1 row in set (8.01 sec)

那是8秒太慢了

此查询的解释扩展

 +----+--------------------+-------+--------+-------------------+-------------+---------+------------+---------+----------+--------------------------+
 | id | select_type        | table | type   | possible_keys     | key         | key_len | ref        | rows    | filtered | Extra                    |
 +----+--------------------+-------+--------+-------------------+-------------+---------+------------+---------+----------+--------------------------+
 |  1 | PRIMARY            | t1    | index  | NULL.             | PRIMARY     | 8       | NULL.      | 1454343 |   100.00 | Using where              |
 |  2 | DEPENDENT SUBQUERY | lt1   | eq_ref | PRIMARY,id3,id4   | PRIMARY     | 8       | const,func |       1 |   100.00 | Using where; Using index |
 |  3 | SUBQUERY           | pt1   | const  | id4               | id4_idx     | 4       |            |       1 |   100.00 | Using index              |
 +----+--------------------+-------+--------+-------------------+-------------+---------+------------+---------+----------+--------------------------+

据我所知,外部查询实际上并没有使用它可能的索引。

在这个查询中我们可能做错了什么。当然它应该运行得更快。

我尝试使用子查询运行外部查询'结果复制粘贴在IN子句中(换句话说,子查询不会运行。它运行得很快。这里是解释扩展然后:

+----+-------------+-------+-------+----------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | type  | possible_keys  | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+-------+----------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t1    | range | PRIMARY,k_id1  | PRIMARY | 4       | NULL |    5 |   100.00 | Using where |
+----+-------------+-------+-------+----------------+---------+---------+------+------+----------+-------------+
噢,是的。这是在MySQL 5.5上运行的

1 个答案:

答案 0 :(得分:0)

你可以使用内连接来避免使用IN子句

  SELECT
    t1.id1,
    sum(t1.value)
  FROM table1 t1
  INNER JOIN (
    SELECT lt1.id4
        FROM lookuptable1 lt1
        WHERE lt1.id3 = (SELECT pt1.id3
                        FROM lookuptable1 pt1
                      WHERE pt1.id4 = 5960)
  ) t on t.id4 = t1.id1  and  t1.id2 = 3

这可以改善您的查询..

确保你在table1(id1,id2)

上有适当的索引