给定的是名为“orders_products”的mySQL表,其中包含以下相关字段:
这两个字段都已编入索引。
我正在运行以下查询:
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
答案 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)
尝试一下:
!=
条件,这很难处理 - 您是否可以缩小产品范围并使用多次查找而不是不公平比较?