【问题标题】:When I ORDER BY a computed column, the query slows significantly - Can this be sped up?当我 ORDER BY 计算列时,查询会显着减慢 - 可以加快速度吗?
【发布时间】:2012-06-19 23:41:59
【问题描述】:

以下查询需要 25 秒以上才能完成:

SELECT c.* , (c.age+ (UNIX_TIMESTAMP()-UNIX_TIMESTAMP(c.newdate))) AS ranking , IF(uc.id_user = 7,1,0) AS favorite
FROM c 
LEFT OUTER JOIN uc ON uc.id_cluster = c.id AND uc.id_user = '7' 
LEFT OUTER JOIN d ON d.id_cluster = c.id 
LEFT OUTER JOIN dt0 ON dt0.id_document = d.id 
LEFT OUTER JOIN t0 ON dt0.id_term = t0.id 
WHERE MATCH(t0.normalizacion) AGAINST ('term' IN NATURAL LANGUAGE MODE) 
GROUP BY c.id 
ORDER BY ranking ASC 
LIMIT 30

索引:

  • c.id PRIMARY
  • c.age 索引
  • c.newdate 索引
  • uc.id_user, uc.id_cluster PRIMARY
  • d.id PRIMARY
  • d.id_cluster 索引
  • dt0.id_document, dt0.id_term PRIMARY
  • dt0.id_document 索引
  • dt0.id_term 索引
  • t0.id 主要
  • t0.normalizacion FULLTEXT

如果我删除 ORDER BY 子句,只需要 2 秒。

我一直在搜索,发现 GROUP BY 和 ORDER BY 必须使用相同的索引(尝试按 c.id 排序并花费 2 或 3 秒)。如何将查询更改为更快?

【问题讨论】:

  • 2 秒可以接受吗?
  • @cheeken 是的。特别考虑到当前的 25 秒。
  • 这里的基本问题是不能通过排名来索引,因为它是实时计算的。我不确定你的表结构和列的含义,但不知何故你应该尝试有一个固定的列来排序。
  • @cen 我尝试创建一个列 c.age2 = c.age-UNIX_TIMESTAMP(c.newdate) 并按它排序(因为 UNIX_TIMESTAMP() 是一个常量,可以出于排序目的而删除)。但是,这并没有缩短查询的时间。
  • @cen 是的。但我认为 MySQL 不能使用该索引,因为它使用 c.id 进行分组。

标签: mysql sql-order-by query-optimization


【解决方案1】:

(巩固上面的讨论)

您无法通过计算结果有效地排序。要使此查询快速运行,请创建一个包含c.age-UNIX_TIMESTAMP(c.newdate)ranking 列。然后在id ranking 上创建一个索引,即CREATE INDEX id_ranking ON c (id, ranking) 以使 GROUP BY 和 ORDER BY 都被索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多