MySQL在哪里不是非常慢

时间:2013-01-05 02:02:54

标签: mysql sql query-optimization

下面是存储过程中的SQL语句(为简洁起见而截断):

SELECT * 
FROM item a 
WHERE a.orderId NOT IN (SELECT orderId FROM table_excluded_item);

此声明需要30秒左右!但是,如果我删除内部SELECT查询,它将降至1秒。 table_excluded_item并不大,但我怀疑内部查询执行的次数超出了预期。

有更有效的方法吗?

3 个答案:

答案 0 :(得分:18)

使用LEFT JOIN

SELECT  a.* 
FROM    item a 
        LEFT JOIN table_excluded_item b
            ON a.orderId = b.orderId
WHERE   b.orderId IS NULL

确保已将两个表中的orderId编入索引。

答案 1 :(得分:5)

左连接方法的问题是在生成输出时可能会处理重复记录。有时,事实并非如此。 。 。根据这个article,MySQL确实在列被索引时正确优化left outer join,即使存在重复项。不过,我承认仍然持怀疑态度,这种优化总是会发生。

MySQL有时在使用子查询优化IN语句时遇到问题。最好的修复是相关的子查询:

SELECT * 
FROM item a 
WHERE not exists (select 1
                  from table_excluded_item tei
                  where tei.orderid = a.orderid
                  limit 1
                 )

如果table_excluded_item.orderid上有索引,那么这将扫描索引并停在第一个值(limit 1可能不是必需的)。这是在MySQL中实现所需的最快,最安全的方法。

答案 2 :(得分:1)

尝试此操作并与LEFT JOIN查询时间进行比较:

SELECT * 
FROM item a 
HAVING orderId NOT IN (SELECT orderId FROM table_excluded_item);

由于HAVING假定限制条件(WHERE)是结果集的一部分,因此不赞成使用HAVING时可以使用orderId。但我认为在这种情况下它更有意义(因为它是结果集的一部分),并且因为它比LEFT JOIN方法更清楚。

它可能实际上有点慢,但发布结果,以便我们知道它是否比原始查询更好。