信息
目前,我正在使用两个表 - 一个POST表,用于保存单个帖子的数据;还有一个FAVORITES表,用于保存选择在其个人资料中保存收藏帖子的用户的数据。
表格如下:
在POSTS表上,id上只有一个主键,没有设置索引。在收藏夹上,我有一个我正在测试的组合索引(postid,deviceid)。
POSTS表包含约。 10,000个条目。
FAVORITES表包含约。 4,680,500个参赛作品。
我用来从特定deviceid获取收藏夹的查询是:
SELECT post FROM POSTS
WHERE id IN
(SELECT postid FROM favourites WHERE deviceid="12d4a4a4a4a4a4a");
问题:
随着返回的数据量以及具有多个收藏夹的多个设备,使用上述查询和子查询,查询对于特定设备的COUNT个收藏夹和/或SELECT可能需要7-10秒以上。如果在高峰期发生这种情况,您显然可以想象可能导致的问题。
缓存查询结果是一个选项,但由于数据非常具体,因为同一个用户不是多次调用查询,而是独特的实例,我认为有更好的解决方案。另一方面,缓存需要很短暂,这将使其利益无效。
我知道索引的方法,我熟悉外键,但我不确定它们是否以及如何在查询和子查询之间实现以提高性能。
非常感谢任何建议/指导。
干杯,
贾里德
答案 0 :(得分:0)
为什么要使用子查询?你试过加入吗?
SELECT post FROM posts INNER JOIN favourites ON posts.id=favourites.postid WHERE deviceid="12d4a4a4a4a4a4a"
由于post
字段不在任何索引中,因此您不会(仅)使用索引来检索查询结果。因此,实际上您可以通过一次查询从posts
获取所有匹配的ID,然后在第二次获取post
值来节省时间。
使用EXPLAIN SELECT...
也可以帮助您优化此查询。你试过了吗?
答案 1 :(得分:0)
SELECT post FROM POSTS
INNER JOIN favourites ON POSTS.id=favourites.postid
WHERE favourites.deviceid="12d4a4a4a4a4a4a");
将favourites
中的索引拆分为deviceid
上的2个索引中的索引和postid
上的索引
答案 2 :(得分:0)
您可以采取一些措施来提高绩效:
将device_id分离为带有代理主键(int)的设备表和device_id varchar上的非聚集索引。收藏夹表应仅包含设备表代理键。这应该使收藏夹表更小,并应使您的收藏夹表索引更小。索引越小,表越小,搜索的速度就越快。
您的收藏夹表索引错误。它不应该是(post_id,device_id)。它应该是(device_id,post_id),因为您的查询需要首先按device_id搜索。由于您的收藏表行非常小,我质疑在索引中包含post_id的值。对于查询速度可能略有改善而言,这是不值得的额外空间。
编辑:你需要索引中的post_id来保持条目的唯一性(只需确保device_id是第一个)。
答案 3 :(得分:0)
在MySQL上,复合索引只能按照定义键的顺序使用。因此,对于索引(postid, deviceid)
,如果您有postid
并且需要deviceid
,则只能使用索引。在您的查询中,您正在做相反的事情 - 您有一个常量deviceid
并想要相应的postid
。所以你的查询没有使用任何索引。
More information on mysql composite indexes。
您应该添加deviceid
索引或反转索引,使其为(deviceid, postid)
。
顺便说一下,你的favorites
表看起来很像一个联结表。考虑一下您是否需要id
列。