我有一个SQL查询需要很长时间才能在MySQL上运行(需要几分钟)。查询是针对一个超过1亿行的表运行的,所以我并不感到惊讶它的速度很慢。但理论上,应该可以加快速度,因为我真的只想从大表中取回行(让我们称之为A)在另一个表B中有一个引用。
所以我的查询是:
SELECT id FROM A, B where A.ref = B.ref;
(A有超过1亿行; B只有几千行)。
我添加了INDEXes:
alter table A add index(ref);
alter table B add index(ref);
但它仍然很慢(几分钟 - 我会对一分钟感到满意)。
不幸的是,我坚持使用MySQL 4.1.22,所以我无法使用视图。
我宁愿不将A中的所有相关行复制到一个单独的较小的表中,因为我需要的行会不时更改。另一方面,目前这是我能想到的唯一解决方案。
欢迎任何建议!
编辑:这是在我的查询上运行EXPLAIN的输出:
+----+-------------+------------------------+------+------------------------------------------+-------------------------+---------+------------------------------------------------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------------------+------+------------------------------------------+-------------------------+---------+------------------------------------------------+-------+-------------+
| 1 | SIMPLE | B | ALL | B_ref,ref | NULL | NULL | NULL | 16718 | Using where |
| 1 | SIMPLE | A | ref | A_REF,ref | A_ref | 4 | DATABASE.B.ref | 5655 | |
+----+-------------+------------------------+------+------------------------------------------+-------------------------+---------+------------------------------------------------+-------+-------------+
(在编写我的原始查询示例时,我选择使用“ref”作为我的列名,这恰好与其中一种类型相同,但希望这不会太混乱......)
答案 0 :(得分:2)
查询优化器可能已经尽力而为,但是在不太可能的情况下,它首先读取巨型表(A),您可以使用STRAIGHT_JOIN
语法明确告诉它首先读取B:
SELECT STRAIGHT_JOIN id FROM B, A where B.ref = A.ref;
答案 1 :(得分:1)
从答案来看,您似乎正在使用SQL做最有效的事情。 A表似乎是一个大问题,如何将它分成三个单独的表,有点像本地版本的分片?或者,是否值得将B表非规范化为A表,假设B没有太多列?
最后,你可能只需购买一个更快的盒子来运行它 - 马力无法替代!
祝你好运。答案 2 :(得分:0)
SELECT A FROM FROM JOIN B ON A.ref = B.ref
您可以通过使用适当类型的连接进一步优化,例如LEFT JOIN