为什么加入子查询是如此之慢?

时间:2014-05-01 10:43:45

标签: mysql sql

请考虑以下查询:

SELECT
  ...
FROM table1
LEFT JOIN table2 ...
LEFT JOIN table3 ...
LEFT JOIN table4 ...
LEFT JOIN table5 ...
LEFT JOIN
(
SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id
) temp ON temp.id = table1.id
WHERE temp.qty = 123
GROUP BY table1.id

此查询非常慢,但是当我执行

SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id
单独来说,它的速度非常快,它只返回少量(20-30)行...

我当前的解决方案是带索引的临时表,我用数据填充它,然后我使用join:

DROP TABLE IF EXISTS tmp_counts;
CREATE TABLE tmp_counts id INT(11), qty INT(11) ...
INSERT INTO tmp_counts (id,qty) (SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id);
SELECT
  ...
FROM table1
LEFT JOIN table2 ...
LEFT JOIN table3 ...
LEFT JOIN table4 ...
LEFT JOIN table5 ...
LEFT JOIN tmp_counts ON tmp_counts.id = table1.id
WHERE tmp_counts.qty = 123
GROUP BY table1.id

它工作得非常快,但我觉得这是一个难看的解决方案。

MySQL真的是那么愚蠢我需要自己手动做mysql工作吗?

1 个答案:

答案 0 :(得分:3)

MySQL并非 愚蠢。优化数据库很复杂。事实上,当你考虑它时,很少有软件可以在如此多种不同的情况下进行这样的优化。程序和面向对象语言 - 告诉他们该做什么。在SQL中,我们说出我们想要的东西,让优化器找到最好的。反过来,最好的方法可能在很大程度上取决于基础数据。

有时优化器是错误的。有时我们可以说服它。这里的问题很可能是连接顺序或连接算法的选择。解决这类问题的一种方法是用select中的相关子查询替换子查询:

选择

SELECT . . .,
       (SELECT COUNT(*)
        FROM other
        WHERE . . . AND
              other.id = table1.id
       ) as qty
  ...
FROM table1
LEFT JOIN table2 ...
LEFT JOIN table3 ...
LEFT JOIN table4 ...
LEFT JOIN table5 ...
GROUP BY table1.id;

反过来,可以通过在other上创建索引来进一步优化。至少,这将是other.id