我正在尝试提供一项功能,我可以在其中显示朋友查看次数最多的页面。我的朋友表有 570 万行,视图表有 530 万行。目前我只想在这两个表上运行一个查询,并找到一个人的朋友查看次数最多的 20 个页面 id。
这是我现在的查询:
SELECT page_id
FROM `views` INNER JOIN `friendships` ON friendships.receiver_id = views.user_id
WHERE (`friendships`.`creator_id` = 143416)
GROUP BY page_id
ORDER BY count(views.user_id) desc
LIMIT 20
这是一个解释的样子:
+----+-------------+-------------+------+-----------------------------------------+---------------------------------+---------+-----------------------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+------+-----------------------------------------+---------------------------------+---------+-----------------------------------------+------+----------------------------------------------+
| 1 | SIMPLE | friendships | ref | PRIMARY,index_friendships_on_creator_id | index_friendships_on_creator_id | 4 | const | 271 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | views | ref | PRIMARY | PRIMARY | 4 | friendships.receiver_id | 11 | Using index |
+----+-------------+-------------+------+-----------------------------------------+---------------------------------+---------+-----------------------------------------+------+----------------------------------------------+
views 表有一个主键 (user_id, page_id),你可以看到它正在被使用。友谊表的主键为 (receiver_id, creator_id),二级索引为 (creator_id)。
如果我在没有 group by 和限制的情况下运行此查询,则此特定用户大约有 25,000 行 - 这是典型的。
在最近的实际运行中,这个查询也执行了 7 秒,这对于 Web 应用程序中的体面响应来说太长了。
我想知道的一件事是我是否应该将二级索引调整为(creator_id,receiver_id)。不过,我不确定这会带来多大的性能提升。根据这个问题的答案,我今天可能会尝试一下。
您能看到可以重写查询以使其快速变亮的任何方式吗?
更新:我需要对其进行更多测试,但如果我不在数据库中进行分组和排序,但之后在 ruby 中进行,我的讨厌的查询似乎效果更好。总时间要短得多——似乎缩短了大约 80%。也许我的早期测试存在缺陷——但这绝对值得更多调查。如果是真的 - 那么 wtf 是 Mysql 在做什么?