我仍在学习 MySQL。我可能犯了一个非常基本的错误,我准备在这里接受惩罚......
这个查询试图做的是根据他们发表的书评和食谱评论的数量从我们的网站中选择排名靠前的成员。
我在 SQL 查询本身中计算总数。查询速度很慢(9 秒),考虑到我们目前只有 400 名成员和几千条评论,而且增长速度非常快,因此肯定无法扩展。
我假设它在此处进行全表扫描,并且计算正在减慢它的速度,但我不知道执行此操作的替代方法并且希望获得一些智慧。
SQL语句如下:
SELECT users.*, COUNT( DISTINCT bookshelf.ID ) AS titles, COUNT( DISTINCT book_reviews.ID ) as bookreviews, COUNT( DISTINCT recipe_reviews.ID ) AS numreviews, COUNT( DISTINCT book_reviews.ID ) + COUNT( DISTINCT recipe_reviews.ID ) as reviewtotal
FROM users
LEFT OUTER JOIN recipe_reviews ON recipe_reviews.user_id = users.ID
LEFT OUTER JOIN book_reviews ON book_reviews.user_id = users.ID
LEFT OUTER JOIN bookshelf ON users.ID = bookshelf.user_id
GROUP BY users.ID
ORDER BY reviewtotal DESC
LIMIT 8
这里是解释:
+----+-------------+----------------+-------+-------------------+-------------------+---------+---------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------+-------+-------------------+-------------------+---------+---------------------+------+---------------------------------+
| 1 | SIMPLE | users | index | NULL | PRIMARY | 4 | NULL | 414 | Using temporary; Using filesort |
| 1 | SIMPLE | recipe_reviews | ref | recipe_reviews_fk | recipe_reviews_fk | 5 | users.ID | 12 | |
| 1 | SIMPLE | book_reviews | ref | user_id | user_id | 5 | users.ID | 4 | |
| 1 | SIMPLE | bookshelf | ref | recipe_reviews_fk | recipe_reviews_fk | 5 | users.ID | 13 | |
+----+-------------+----------------+-------+-------------------+-------------------+---------+---------------------+------+---------------------------------+
更新和解决:
我意识到,并且@recursive 确认,查询是问题的根源。我从中得到笛卡尔积。我将其重写为一系列子查询,最终的工作代码在这里:
SELECT *, bookreviews + recipereviews AS totalreviews
FROM (SELECT users.*,
(SELECT count(*) FROM bookshelf WHERE bookshelf.user_id = users.ID) as titles,
(SELECT count(*) FROM book_reviews WHERE book_reviews.user_id = users.ID) as bookreviews,
(SELECT count(*) FROM recipe_reviews WHERE recipe_reviews.user_id = users.ID) as recipereviews
FROM users) q
这会以毫秒为单位给出结果。也有一些方法可以通过 JOIN 来做到这一点。参见 How to add together the results of several subqueries?如果你想跟进这个。
最佳答案
对于这样的功能,使用某种缓存总是有帮助的...
每晚为所有用户创建总和并将这些总和存储在用户那里可能已经有所帮助。这将有很大帮助并加快您的搜索速度。
您还应该以某种方式将此请求缓存至少一到五分钟,因为您将独立于登录用户执行相同的请求。
关于sql - 执行 count() 计算会减慢我的 mysql 查询速度吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2030032/