【问题标题】:Slow query when using ORDER BY使用 ORDER BY 时查询慢
【发布时间】:2010-10-27 10:42:59
【问题描述】:

这是查询(最大的表大约有 40,000 行)

SELECT
  Course.CourseID,
  Course.Description,
  UserCourse.UserID,
  UserCourse.TimeAllowed,
  UserCourse.CreatedOn,
  UserCourse.PassedOn,
  UserCourse.IssuedOn,
  C.LessonCnt
FROM
  UserCourse
INNER JOIN
  Course
USING(CourseID)
INNER JOIN
(
  SELECT CourseID, COUNT(*) AS LessonCnt FROM CourseSection GROUP BY CourseID
) C
USING(CourseID)
WHERE 
  UserCourse.UserID = 8810

如果我运行它,它会执行得非常快(大约 0.05 秒)。它返回 13 行。

当我在查询末尾添加 ORDER BY 子句(按任何列排序)时,查询大约需要 10 秒。

我现在在生产中使用这个数据库,一切正常。我所有的其他查询都很快。

有什么想法吗?我在 MySQL 的查询浏览器和命令行中运行了查询。 ORDER BY 在这两个地方都非常缓慢。

编辑: Tolgahan ALBAYRAK 解决方案有效,但谁能解释它为什么有效?

【问题讨论】:

  • 为什么有效?子查询将结果放入结果集中,对结果集进行排序比让默认查询执行在排序过程中计数要快得多。

标签: mysql sql-order-by


【解决方案1】:

也许这有帮助:

SELECT * FROM (    
     SELECT
      Course.CourseID,
      Course.Description,
      UserCourse.UserID,
      UserCourse.TimeAllowed,
      UserCourse.CreatedOn,
      UserCourse.PassedOn,
      UserCourse.IssuedOn,
      C.LessonCnt
    FROM
      UserCourse
    INNER JOIN
      Course
    USING(CourseID)
    INNER JOIN
    (
      SELECT CourseID, COUNT(*) AS LessonCnt FROM CourseSection GROUP BY CourseID
    ) C
    USING(CourseID)
    WHERE 
      UserCourse.UserID = 8810
) ORDER BY CourseID

【讨论】:

  • 嗯,这行得通(让它执行得很快)。你知道为什么吗?我以前从来没有这样做过。
  • 40k 不是那么多记录;通常必须处理数百万,因此您的里程可能会有所不同,但这可能有助于进一步提高性能,因为连接将在减少的数据集上完成。 ... FROM (Select * from UserCourse Where UserID = 8810 ) UserCourse
  • tvanfosson,我一直以为ORDER BY是在返回结果后才处理的。我想不一定是这样。我得再调查一下。谢谢。
【解决方案2】:

您要排序的列是否已编入索引?

索引大大加快了排序和过滤的速度。

【讨论】:

  • 使用顺序中的任何列提到的操作会降低性能
  • 任何列,包括索引列,都会使其运行缓慢。
【解决方案3】:

您正在从“UserCourse”中进行选择,我认为它是课程和用户之间的连接表(多对多)。 您应该在“UserCourse”表中索引您需要排序的列。

假设您要“按 CourseID 排序”,那么您需要在 UserCourse 表中对其进行索引。

按连接表中不存在的任何其他列(即 UserCourse)进行排序可能需要在连接表上进行进一步的非规范化和索引以优化速度; 换句话说,您需要在连接表中拥有该列的副本并对其进行索引。

附言 Tolgahan Albayrak 给出的答案虽然对这个问题是正确的,但在执行“LIMIT x”查询的情况下不会产生预期的结果。

【讨论】:

    【解决方案4】:

    您是否更新了数据库中的统计信息?我遇到了类似的问题,我有 2 个相同的查询,唯一的区别是一个大写字母,一个以 1/2 秒的速度返回,另一个花了将近 5 分钟。更新统计信息解决了问题

    【讨论】:

    • 奇怪,我刚刚遇到了类似的问题,更新统计信息确实解决了这个问题。几天前,我们不得不为这个环境恢复一个数据库备份,这可能首先导致了这种情况。
    【解决方案5】:

    意识到答案为时已晚,但是我刚刚遇到了类似的问题,通过将查询时间从几秒增加到 5 分钟来添加订单,并尝试了大多数其他加快速度的建议,注意到 /tmp 文件的位置此查询为 12G。更改了查询,使得返回的 varchar(20000) 字段是“trim(”ed 并且性能显着提高(回到秒)。所以我想值得检查一下您是否在查询中返回大型 varchars,如果是,处理它们(也许是 substring(x, 1, length(x))?? 如果你不想修剪它们。 查询返回 500k 行,/tmp 文件表明每行使用大约 20k 数据。

    【讨论】:

      【解决方案6】:

      here.之前有人问过类似的问题

      它也可能对您有所帮助。基本上它描述了使用复合索引以及 order by 的工作原理。

      【讨论】:

        【解决方案7】:

        今天我遇到了同样的问题。当我按连接表中的字段对结果集进行排序时,整个查询速度非常慢,需要一百多秒。

        服务器正在运行 MySQL 5.0.51a,我偶然注意到,相同的查询运行速度与它在使用 MySQL 5.1 的服务器上的运行速度一样快。在比较该查询的解释时,我发现索引的使用和处理显然发生了很大变化(至少从 5.0 -> 5.1)。

        所以如果你遇到这样的问题,也许你的解决办法就是简单地升级你的 MySQL

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-15
          • 1970-01-01
          • 2023-03-21
          • 1970-01-01
          • 2019-09-12
          • 2021-11-17
          • 2021-04-22
          • 1970-01-01
          相关资源
          最近更新 更多