如果以前曾经问过这个问题,但是有什么办法可以道歉,我可以优化这个查询以便更快地运行。在一分钟它需要大约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()创建的数据进行排序,而且没有索引。我不能不对它进行排序,因为它给了我所需的结果,但我还能做些什么来防止它减慢查询速度?
感谢。
答案 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_id
和MAX(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