为啥这个 mySQL 查询非常慢?
Posted
技术标签:
【中文标题】为啥这个 mySQL 查询非常慢?【英文标题】:Why is this mySQL query extremely slow?为什么这个 mySQL 查询非常慢? 【发布时间】:2013-07-09 13:33:24 【问题描述】:给定一个名为“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),这可能是内存问题吗?
有没有办法准确判断 mySQL 花了这么长时间?
解释的输出:
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
【问题讨论】:
EXPLAIN?你能发布解释输出吗? 你有关于 orders_id 和 products_id 的索引吗? 提供表结构、索引和查询目的或预期输出。 orders_id 和 products_id 都有索引。添加了对问题的解释输出。 啊,我的老朋友“使用文件排序”。尝试删除ORDER
看看是否有帮助,至少作为隔离问题的一种方式。
【参考方案1】:
使用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字段上查找(再次快速),但在连接条件中过滤以计算 其他 产品。
【讨论】:
就像一个魅力,现在查询几乎不需要时间。 不用担心。顺便说一句,您对group by
和 order by
的编辑是不必要的 - 无论哪种方式都可以正确执行:SQL 标准提供对列 position 的引用(而不是列 expression) 用于这些子句。
我同意 WHERE ID IN (subquery)
的性能在几乎所有 MySQL 数据库中都是出了名的差。
@ypercube WHERE IN ()
哪些数据库在 IYHO 中表现良好?
@ypercube 适当编辑,不使用 mysql 刷 tar 其他数据库【参考方案2】:
试试这些:
-
MySQL 不使用子查询优化 IN - 将表连接在一起。
您的查询包含
!=
条件,这很难处理 - 您能否缩小产品范围并使用多个查找而不是不公平比较?
【讨论】:
以上是关于为啥这个 mySQL 查询非常慢?的主要内容,如果未能解决你的问题,请参考以下文章