【问题标题】:MySQL slow group by/order byMySQL慢速分组/排序
【发布时间】:2012-01-27 17:23:17
【问题描述】:

以下查询相对较慢(0.7 秒,约 6k 行)

SELECT items.*, COUNT(transactions.ID)
   FROM items
  INNER JOIN users ON (items.USER = users.ID)
   LEFT JOIN transactions ON (items.id = transactions.item)
  WHERE items.ACTIVE = 1
    AND items.DELETED_AT IS NULL
  GROUP BY items.ID
  ORDER BY items.DATE DESC
  LIMIT 20

但是当按 items.ID DESC 而不是 items.DATE 排序时,速度会显着加快。事务连接是一个大表(约 250k 行)并且是一对多的。日期列有一个索引。

有什么方法可以普遍提高 ORDER BY 的性能?

编辑:items.user、transactions.item 和 items.date 的索引。项目有 49 列,用户 76 列,交易 17 列。

【问题讨论】:

  • 你能提供三个表的架构,尤其是索引吗?
  • 我唯一能想到的就是首先选择由 WHERE 子句过滤并在子查询中按日期排序的项目,(或者在视图中,如果 MySQL 不支持子查询中的 ORDER BY,)然后在一个封闭的查询中做你的连接。 (我不会写这个作为答案,因为 SO 不鼓励投机性的答案。)
  • 您是否尝试在GROUP BY 中包含items.DATE(也位于第一位)?

标签: mysql performance join sql-order-by


【解决方案1】:

索引会影响ORDER BY 子句的性能。这个MySQL manual page 可能值得你花时间。本质上,如果您按作为 MySQL 用于查询的索引的一部分的列进行排序,MySQL 可以使用索引而不是数据本身进行排序。

在您的特定查询中,DATE 列具有索引这一事实并不重要,因为您的查询中可能未使用该索引。您的WHERE 语句包含items.ACTIVEitems.DELETED_AT,并且如果这些列具有用于WHERE 的索引,但不包括DATE 列,则MySQL 无法使用该索引进行排序by DATE,并且很可能诉诸文件排序。

如果您能想出一个可供WHEREORDER BY 使用的索引,您将获得优化提升。在这种情况下,items.ACTIVE 似乎是一个低基数列,因此假设 items.DELETED_AT 是一个日期,我可能会为该表尝试像 INDEX(DELETED_AT,DATE) 这样的索引。

使用EXPLAIN SELECT... 也可以了解更多关于那里正在发生的事情,您可能会获得一些进一步的见解。

【讨论】:

    【解决方案2】:
    SELECT *
    FROM (SELECT * FROM wp_users WHERE 1 GROUP BY ID limit 0,10) as X
    ORDER BY ID DESC
    

    上面的查询很完美,我在一个很长的数据库中使用过。它按我们从内部选择查询中获得的 10 个 OR (xx) 项的列表排序,因此速度非常快!

    【讨论】:

    • 你甚至没有使用 Left_join
    【解决方案3】:

    这些是可以(阅读不保证)帮助的事情。

    1. 删除项目上的 *。* 并单独列出每个字段。 49 列很多;你真的需要它们吗?
    2. 通常引擎会优化查询,以便限制 在连接上考虑标准。也许使用的计划 引擎没有这样做(需要解释计划结果才能知道)所以 重新安排 where 子句并加入可能(不太可能)有助于 迫使引擎考虑这一点。 (见下文)
    3. 如果有很多更新、插入、删除操作,则重建表统计信息 随着时间的推移发生,可能表统计信息已关闭并且 需要 rebuilt 每张桌子
    SELECT items.[list fields], COUNT(transactions.ID)
       FROM items
      INNER JOIN users ON (items.USER = users.ID)
            AND items.Active=1 
            AND items.DELETED_AT is Null
       LEFT JOIN transactions ON (items.id = transactions.item)
      GROUP BY items.ID
      ORDER BY items.DATE DESC
      LIMIT 20
    

    【讨论】:

      猜你喜欢
      • 2013-09-11
      • 2011-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 2010-10-04
      • 2020-05-16
      相关资源
      最近更新 更多