【问题标题】: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 看看是否有帮助,至少作为隔离问题的一种方式。

标签: mysql sql query-performance where-in


【解决方案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 byorder by 的编辑是不必要的 - 无论哪种方式都可以正确执行:SQL 标准提供对列 position 的引用(而不是列 expression) 用于这些子句。
  • 我同意 WHERE ID IN (subquery) 的性能在几乎所有 MySQL 数据库中都是出了名的差。
  • @ypercube WHERE IN () 哪些数据库在 IYHO 中表现良好?
  • @ypercube 适当编辑,不使用 mysql 刷 tar 其他数据库
【解决方案2】:

试试这些:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 2011-10-19
    • 2020-09-10
    • 2012-07-27
    • 2012-06-13
    相关资源
    最近更新 更多