【问题标题】:What should be indexed to improve performance?应该索引什么来提高性能?
【发布时间】:2011-09-04 03:36:06
【问题描述】:

鉴于此查询,应为哪些列或哪些列建立索引以优化查询性能?

SELECT *
  FROM `activities`
 WHERE (user_id = 90000 AND activity_type_id IN(300,400,808,9494))
 ORDER BY created_at DESC
 LIMIT 70

【问题讨论】:

  • 你能提供更多关于模式的信息吗?例如,user_id 是主键(因此已经有唯一索引)吗?
  • @Cole:user_id 不太可能是activities 表中的(唯一)主键列。它可能是(可能是)主键的一部分。
  • @Jonathan 谢谢,我刚刚意识到我从未考虑将复合键添加到我自己的表中。我必须记住这些。

标签: mysql sql indexing


【解决方案1】:

一般来说,选择过滤器可以使用user_idactivity_type_id 或两者上的索引(以任意顺序)。

排序操作可能能够在created_at 上使用过滤器。

对于这个查询,(user_id, activity_type_id) 上的复合索引可能会给出最好的结果,假设 MySQL 可以实际使用它。否则,索引user_id 可能比索引activity_type_id 更好,因为它可能提供更好的选择性。考虑这一点的一个原因是,如果它使用activity_type_id 上的索引,则需要扫描索引的 4 个子部分,而如果它仅使用user_id 上的索引,则只需扫描一个子部分。

尝试依赖索引进行排序可能意味着全表扫描,因此不太可能带来好处。我不会在created_at 上创建索引来支持这个查询;可能还有其他有用的查询。

【讨论】:

    【解决方案2】:

    当然,WHERE 子句中的所有列都应该被索引。

    但是 IN 子句可能需要进行表扫描。

    我认为阅读这些答案可能会有所帮助:

    MySQL not using indexes with WHERE IN clause?

    【讨论】:

      【解决方案3】:

      您正在查找 user_id 和 activity_type_id,所以在这两列上创建索引。

      【讨论】:

        【解决方案4】:

        我只会索引user_id..

        【讨论】:

          【解决方案5】:

          假设您没有在实际生产代码中隐藏 JOIN,索引“activity_type_id”应该是最好的。

          【讨论】:

            【解决方案6】:

            我会在活动表上添加两个索引,一个在 (user_id, activity_type_id) 上,另一个在 (created_dt) 上。我还会仔细研究实际使用了“活动”表中的哪些字段;如果您可以减少检索到的字段数量,您可能会缩短响应时间。我还会在对数据库进行任何更改之前获取查询计划,然后将其与进行任何/所有更改后生成的计划进行比较。

            分享和享受。

            【讨论】:

              【解决方案7】:

              我根本不会创建任何额外的索引,而是我会设计我的表,以便充分利用 innodb 集群主键!

              create table activities
              (
              user_id int unsigned not null,
              activity_id smallint unsigned not null,
              primary key (user_id, activity_id) -- composite clustered primary key order is important
              )
              engine=innodb;
              

              create table activities
              (
              user_id int unsigned not null,
              activity_id smallint unsigned not null,
              primary key (activity_id, user_id) -- hmmmm the other way round, why is that ?
              )
              engine=innodb;
              

              另外,请阅读以下内容:

              MySQL and NoSQL: Help me to choose the right one

              How to avoid "Using temporary" in many-to-many queries?

              60 million entries, select entries from a certain month. How to optimize database?

              Rewriting mysql select to reduce time and writing tmp to disk

              希望它有所帮助并记住 innodb FTW ;)

              【讨论】:

                【解决方案8】:

                要做出正确的决定,您必须考虑以下几点:

                如果 user_id 是主键的一部分(你说它可能是),那么主键是表的聚集索引吗?如果是,user_id 是否在聚集索引的第一个位置?如果是这样,那么您希望每个用户有多少活动?如果每个用户有 1-40 个活动,那么添加另一个索引将没有用,并且会损害插入性能。原因是用户的所有活动行都将聚集在一起,并且很可能位于同一个数据库页面上,因此将 activity_type_id 添加到索引中无济于事。

                如果主键没有聚集,并且user_id不在主键的第一位,或者user_id不在主键中,那么你最好是一个非聚集索引,带有user_id,activity_type_id .查询优化器应该足够聪明以使用索引,因为即使存在 IN 子句,user_id 和 activity_type_id 都在 where 语句中。您还可以在索引末尾添加 created_at ,因为您是以这种方式对查询结果进行排序的。

                注意专门为一个查询创建索引,但如果查询被大量使用,则通常是必要的。

                【讨论】:

                  猜你喜欢
                  • 2016-05-23
                  • 2013-12-05
                  • 2014-09-06
                  • 1970-01-01
                  • 2017-11-19
                  • 2015-04-28
                  • 2010-11-08
                  • 1970-01-01
                  • 2021-09-19
                  相关资源
                  最近更新 更多