使用MAX()优化MySQL查询

时间:2011-12-18 22:34:25

标签: mysql max

如果以前曾经问过这个问题,但是有什么办法可以道歉,我可以优化这个查询以便更快地运行。在一分钟它需要大约2秒,虽然这不是一个巨大的数额,它是我网站上最慢的查询,所有其他查询花费少于0.5秒。

这是我的问题:

SELECT SQL_CALC_FOUND_ROWS MAX(images.id) AS maxID, celebrity.* FROM images
JOIN celebrity ON images.celeb_id = celebrity.id
GROUP BY images.celeb_id
ORDER BY maxID DESC
LIMIT 0,20

这是一个解释:

1 SIMPLE celebrity ALL PRIMARY NULL NULL NULL 536 Using temporary; Using filesort
1 SIMPLE images ref celeb_id celeb_id 4 celeborama_ignite.celebrity.id 191

我对如何进一步提高此查询的性能感到茫然。我不是很熟悉MySQL,但我知道它很慢,因为我正在对MAX()创建的数据进行排序,而且没有索引。我不能不对它进行排序,因为它给了我所需的结果,但我还能做些什么来防止它减慢查询速度?

感谢。

5 个答案:

答案 0 :(得分:2)

如果您确实需要快速解决方案 - 那么请不要在运行时执行此类查询。

只需在last_image_id表中创建其他字段celebrity,并在上传新图片时更新它(通过触发器或您的应用程序逻辑,无关紧要)

答案 1 :(得分:1)

我会这样得到最新的图片:

SElECT c.*, i.id AS image_id
FROM celebrity c
JOIN images i ON i.celeb_id = c.id
LEFT OUTER JOIN images i2 ON i2.celeb_id = c.id AND i2.id > i.id
WHERE i2.id IS NULL
ORDER BY image_id DESC
LIMIT 0,20;

换句话说,尝试为ID高于i2的同一名人找到一行i.id。如果外部联接未能找到该匹配项,那么i.id必须是给定名人的最大图像ID。

SQL_CALC_FOUND_ROWS会导致查询运行速度极慢。我发现一些情况下,只删除SQL_CALC_FOUND_ROWS使查询运行速度提高了200倍(但在其他情况下也只能产生一点差异,这取决于表,所以你应该测试两种方式)。

如果您需要等效的SQL_CALC_FOUND_ROWS,只需运行单独的查询:

SELECT COUNT(*) FROM celebrity;

答案 2 :(得分:0)

我认为您需要表(celeb_id, id) images上的复合索引(假设它是MyISAM表),因此GROUP BY celeb_idMAX(id)可以使用此索引。

但是对于大桌子,你可能不得不关注@ zerkms'建议并在表celebrity

中添加新列

答案 3 :(得分:0)

SELECT STRAIGHT_JOIN *
FROM (
  SELECT MAX(id) as maxID, celeb_id as id
  FROM images
  GROUP BY celeb_id
  ORDER by maxID DESC
  LIMIT 0, 20) as ids
JOIN celebrity USING (id);

查询不允许行号预先计算,但需要额外的:

SELECT COUNT(DISTINCT celeb_id)
FROM images;

甚至(如果每个名人都有一张图片):

SELECT COUNT(*) FROM celebrity;

不会花费太多,因为查询缓存可以很容易地缓存它(如果它没有关闭)。

答案 4 :(得分:0)

MYSQL在连接方面表现不佳。我建议将您的查询分成两部分。在第一个查询中选择名人,然后选择图像。简单地避免加入。 查看此链接 - http://phpadvent.org/2011/a-stitch-in-time-saves-nine-by-paul-jones