为什么这个mySQL查询非常慢?

时间:2013-07-11 10:10:30

标签: mysql sql query-performance where-in

给定的是名为“orders_products”的mySQL表,其中包含以下相关字段:

  • products_id
  • orders_id

这两个字段都已编入索引。

我正在运行以下查询:

SELECT products_id, count( products_id ) AS counter
FROM orders_products
WHERE orders_id
IN (
  SELECT DISTINCT orders_id
  FROM orders_products
  WHERE products_id = 85094
)
AND products_id != 85094
GROUP BY products_id
ORDER BY counter DESC
LIMIT 4

此查询需要很长时间,大约20秒。否则数据库不是很忙,并且在其他查询上表现良好。

我想知道,是什么导致查询变得如此缓慢?

表格相当大(大约150万行,大小约为210 mb),这可能是内存问题吗?

有没有办法确切地说明了什么花了我的SQL这么久?

解释输出:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     orders_products     range   products_id     products_id     4   NULL    1577863     Using where; Using temporary; Using filesort
2   DEPENDENT SUBQUERY  orders_products     ref     orders_id,products_id   products_id     4   const   2   Using where; Using temporary

2 个答案:

答案 0 :(得分:4)

使用WHERE ID IN (subquery)的查询与mysql的表现非常糟糕。

但是,对于此类查询的大多数情况,可以将它们重写为JOIN,这个也不例外:

SELECT
    t2.products_id,
    count(t2.products_id) AS counter
FROM orders_products t1
JOIN orders_products t2
    ON t2.orders_id = t1.orders_id
    AND t2.products_id != 85094 
WHERE t1.products_id = 85094
GROUP BY t2.products_id
ORDER BY counter DESC
LIMIT 4

如果要返回其他产品的行(并显示零计数),请将联接更改为LEFT JOIN

注意表的第一个实例如何具有WHERE products_id = X,它允许索引查找并立即减少行数,并且表的第二个实例具有目标数据,但它查找了id字段(再次快速),但在连接条件下进行过滤以计算其他产品。

答案 1 :(得分:1)

尝试一下:

  1. MySQL不会使用子查询优化IN - 将表连接在一起。
  2. 您的查询包含!=条件,这很难处理 - 您是否可以缩小产品范围并使用多次查找而不是不公平比较?