【发布时间】:2012-09-24 15:27:45
【问题描述】:
我在朋友提要查询方面遇到了奇怪的问题 - 这是背景:
我有 3 张桌子
checkin - around 13m records
users - around 250k records
friends - around 1.5m records
在签入表中 - 它列出了用户执行的活动。 (这里有很多索引,但是在 user_id、created_at 和 (user_id,created_at) 上有一个索引。 users 表只是基本的用户信息 user_id 上有一个索引。 朋友表有一个 user_id、target_id 和 is_approved。 (user_id, is_approved) 字段上有索引。
在我的查询中,我试图只下拉任何用户的基本朋友提要 - 所以我一直在这样做:
SELECT checkin_id, created_at
FROM checkin
WHERE (user_id IN (SELECT friend_id from friends where user_id = 1 and is_approved = 1) OR user_id = 1)
ORDER by created_at DESC
LIMIT 0, 15
查询的目标只是为所有用户的朋友以及他们的活动提取 checkin_id 和 created_at。这是一个非常简单的查询,但是当用户的朋友最近有大量活动时,这个查询很快,这里是解释:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY checkin index user_id,user_id_2 created_at 8 NULL 15 Using where
2 DEPENDENT SUBQUERY friends eq_ref user_id,friend_id,is_approved,friend_looku... PRIMARY 8 const,func 1 Using where
作为解释,user_id 是 user_id 上的简单索引 - 而 user_id_2 是 user_id 和 created_at 上的索引。在friends表上,friends_lookup是user_id和is_approved的索引。
这是一个非常简单的查询,完成时间为:显示第 0 - 14 行(共 15 行,查询耗时 0.0073 秒)。
但是,当用户的好友活动不是最近的并且没有很多数据时,相同的查询大约需要 5-7 秒,并且它具有与上一个查询相同的 EXPLAIN - 但需要更长的时间。
似乎对更多朋友没有影响,似乎随着最近的活动而加速。
是否有任何提示可以让任何人优化这些查询,以确保无论活动如何都以相同的速度运行?
服务器设置
这是一个运行 16GB RAM 的专用 MySQL 服务器。它运行的是 Ubuntu 10.10,MySQL 的版本是 5.1.49
更新
所以大多数人建议删除 IN 部分并将它们移动到 INNER JOIN 中:
SELECT c.checkin_id, c.created_at
FROM checkin c
INNER JOIN friends f ON c.user_id = f.friend_id
WHERE f.user_id =1
AND f.is_approved =1
ORDER BY c.created_at DESC
LIMIT 0 , 15
这个查询比 EXPLAIN 中报告的要差 10 倍:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE f ref PRIMARY,user_id,friend_id,is_approved,friend_looku... friend_lookup 5 const,const 938 Using temporary; Using filesort
1 SIMPLE c ref user_id,user_id_2 user_id 4 untappd_prod.f.friend_id 71 Using where
此查询的目标是在同一个查询中获取所有朋友的活动以及您的活动(而不必创建两个查询并将结果合并在一起并按 created_at 排序)。我也无法删除 user_id 上的索引,因为它是另一个查询的重要部分。
有趣的是,当我在一个没有大量活动的用户帐户上运行此查询时,我得到了这样的解释:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE f index_merge PRIMARY,user_id,friend_id,is_approved,friend_looku... user_id,friend_lookup 4,5 NULL 11 Using intersect(user_id,friend_lookup); Using wher...
1 SIMPLE c ref user_id,user_id_2 user_id 4 untappd_prod.f.friend_id 71 Using where
有什么建议吗?
【问题讨论】:
标签: mysql optimization social-networking social