【问题标题】:Proper database indexes with subquery带有子查询的正确数据库索引
【发布时间】:2012-01-22 06:10:14
【问题描述】:

信息

目前,我正在使用两个表 - 一个 POST 表保存单个帖子的数据,另一个 FAVORITES 表保存选择在其个人资料中保存最喜欢的帖子的用户的数据。

表格如下所示:

在 POSTS 表上,id 上只有一个主键,没有我设置的索引。在收藏夹中,我有一个正在测试的组合索引(postid、deviceid)。

POSTS 表包含大约。 10,000 个条目。

FAVORITES 表包含大约。 4,680,500 个条目。

我用来从特定设备 ID 中获取收藏夹的查询是:

SELECT post FROM POSTS 
WHERE id IN 
   (SELECT postid FROM favourites WHERE deviceid="12d4a4a4a4a4a4a");

问题:

由于返回的数据量很大,并且多个设备有多个收藏夹,使用上述查询和子查询查询特定设备的 COUNT 个收藏夹和/或 SELECT 可能需要 7-10 秒以上的时间。在高峰时段发生这种情况时,您显然可以想象可能导致的问题。

缓存查询结果是一种选择,但由于数据非常具体,同一用户不会多次调用查询,而是唯一的实例,我认为有更好的解决方案。另一方面,缓存需要是短暂的,这将抵消它的好处。

我知道索引的方法,并且我熟悉外键,但我不确定是否以及如何在查询和子查询之间实现它们以提高性能。

非常感谢任何建议/指导。

干杯,

贾里德

【问题讨论】:

  • 可以借助执行计划来分析查询性能。你可以为你的帖子发帖吗?

标签: mysql database indexing


【解决方案1】:
SELECT post FROM POSTS 
INNER JOIN favourites ON POSTS.id=favourites.postid 
WHERE favourites.deviceid="12d4a4a4a4a4a4a");

favourites 中的索引分成两个索引,一个在deviceid 上,一个在postid

【讨论】:

  • 这成功了,正如其他人所建议的那样,改变查询并重做索引已经解决了这个问题。谢谢大家。
【解决方案2】:

为什么要使用子查询?你试过加入吗?

SELECT post FROM posts INNER JOIN favourites ON posts.id=favourites.postid WHERE deviceid="12d4a4a4a4a4a4a"

您不会(仅)使用索引来检索查询结果,因为post 字段不在任何索引中。因此,您实际上可能会通过执行一次查询来从 posts 获取所有匹配的 ID,然后再通过一秒钟来获取 post 值来节省时间。

使用EXPLAIN SELECT... 也将帮助您优化此查询。你试过吗?

【讨论】:

    【解决方案3】:

    在 MySQL 上,复合索引只能按照定义键的顺序使用。所以对于索引(postid, deviceid),如果你有一个postid并且需要deviceid,你只能使用索引。在您的查询中,您正在做相反的事情-您有一个常量deviceid 并想要对应的postid。所以你的查询没有使用任何索引。

    More information on mysql composite indexes

    您应该添加deviceid 索引或反转索引以使其成为(deviceid, postid)

    顺便说一句,您的favorites 表看起来很像联结表。考虑一下您是否需要id 列。

    【讨论】:

      【解决方案4】:

      您可以做几件事来提高性能:

      • 使用代理主键(int)和 device_id varchar 上的非聚集索引将 device_id 分离到设备表中。收藏夹表应该只包括设备表代理键。这应该使收藏夹表更小,并且应该使您的收藏夹表索引更小。索引越小,表越小,搜索越快。

      • 您的收藏夹表索引错误。它不应该是(post_id,device_id)。它应该是 (device_id,post_id) 因为您的查询需要先按 device_id 进行搜索。由于您的收藏夹表行太小,我质疑将 post_id 包含在索引中的价值。只是不值得为查询速度的边际提高而额外的空间。

      编辑:您需要索引中的 post_id 来保持条目的唯一性(只需确保 device_id 是第一个)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-30
        • 1970-01-01
        • 2015-06-14
        • 1970-01-01
        相关资源
        最近更新 更多