MySQL JOIN查询耗时太长,无法完成

时间:2009-08-12 12:55:05

标签: mysql query-optimization

我有一个名为users的表,其中包含大约250,000条记录。我有另一个名为staging的表,其中包含大约75,000条记录。暂存只有一列,msisdn。我想查看用户中>不存在的分段行数。

我有以下查询,我在一个小数据子集上测试过,它似乎工作正常:

SELECT
    s.*
    FROM staging s
        LEFT OUTER JOIN users u ON u.msisdn=s.msisdn
        WHERE u.msisdn IS NULL

问题是,当我尝试在250k用户的完整列表上运行此查询时。在我停下来之前它跑了一个小时。有什么办法可以优化这个查询吗?

我已经开始在分段中运行数据子集的查询,但这是可怕的手册:

SELECT
    s.*
    FROM staging s
        LEFT OUTER JOIN users u ON u.msisdn=s.msisdn
        WHERE u.msisdn IS NULL
    LIMIT 0,10000

msisdn是登台表的主键,但它不是表用户的主键。但我不知道这是否有意义。

4 个答案:

答案 0 :(得分:4)

首先,您可以使用EXPLAIN命令查看MySQL正在使用的索引。只需在查询前面写EXPLAIN,结果就会显示它正在使用的索引(如果有的话)。据推测,如果这样(相对)小的数据设置为250,000条记录的速度很慢,那么它不会利用非常有效的索引,您将能够看到哪里。

将查询重写为NOT EXISTS也可能有帮助:

SELECT s.* FROM staging s
WHERE NOT EXISTS (SELECT 1 FROM users WHERE users.misdn = s.misdn)

答案 1 :(得分:1)

将索引放在每个表的msisdn列上。由于它不是users上的PK,因此您需要在其上放置非聚集索引。这应该会极大地加快您的查询速度。

答案 2 :(得分:1)

您可以采取哪些措施来加快此查询:

  • 确保msisdn在两个表中都已编入索引
  • 优化表格
  • 用msisdn
  • 替换*

答案 3 :(得分:0)

我不确定这会有多快,但你可以尝试类似的东西。

select msisdn
from staging
where msisdn not in (select msisdn from users)

此外,请确保两个表中的msisdn列都存在索引。这应该会大大加快速度。