mysql - 优化两个大表上的简单查询

标签 mysql performance optimization query-optimization

我正在尝试提供一项功能,让我可以显示 friend 查看最多的页面。我的 friend 表有 570 万行, View 表有 530 万行。目前我只想对这两个表运行查询并找到一个人的 friend 查看次数最多的 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)。

如果我在没有分组依据和限制的情况下运行此查询,则该特定用户大约有 25,000 行 - 这很正常。

在最近的实际运行中,此查询也执行了 7 秒,这对于 Web 应用程序中的正常响应来说太长了。

我想知道的一件事是我是否应该将二级索引调整为 (creator_id, receiver_id)。我不确定这会带来很大的性能提升。我今天可能会根据这个问题的答案来尝试。

您能看出有什么方法可以重写查询以使其变快吗?

更新:我需要对其进行更多测试,但如果我不在数据库中进行分组和排序,但之后在 ruby​​ 中进行,那么我讨厌的查询似乎会更好。总时间要短得多——看起来大约缩短了 80%。也许我的早期测试存在缺陷 - 但这绝对值得更多调查。如果这是真的 - 那么 Mysql 在做什么?

最佳答案

据我所知,进行这种“闪电般快速”查询的最佳方法是创建一个汇总表,以跟踪每个创建者每页的好友页面浏览量。

您可能希望通过触发器使其保持最新。然后你的聚合已经为你完成了,这是一个简单的查询来获得最多查看的页面。您可以确保在汇总表上有适当的索引,这样数据库甚至不必进行排序即可获得最多的浏览量。

汇总表是在以读取为主的环境中保持聚合类型查询良好性能的关键。您预先完成工作,当更新发生时(不频繁)然后查询(频繁)不需要做任何工作。

如果您的统计数据不必是完美的,并且您的写入实际上相当频繁(页面浏览量可能就是这种情况),您可以在内存中批量处理 View 并在后台处理它们,这样 friend 们在查看页面时不必费力使汇总表保持最新。该解决方案还减少了对数据库的争用(更少的进程更新汇总表)。

关于mysql - 优化两个大表上的简单查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1004672/

相关文章:

java - 如何执行其他架构存储过程?

jquery - 我可以毫无问题地将 UUID 用作 HTML 标记 ID 吗?

performance - 多核/多处理器是否有助于 Web 服务器的性能?

optimization - 汇编语言和优化

python - 如何修复 'Can' t 在 'localhost:3306' 错误上连接到 MySQL 服务器

php - 在 php 中从 mysql 在表行中创建链接(成员列表)

php - 使用 jquery ajax 和 php 实现过滤内容

c++ - openMp:调用动态数组的共享引用时性能严重下降

optimization - 如果我优化大小(z)而不是速度(3),我将更改什么速度增益?

mysql - INSERT SELECT 在 WHERE 条件中使用 UNION 语句