【问题标题】:MySQL indexes - how many are enough?MySQL 索引 - 多少才足够?
【发布时间】:2010-11-19 15:45:19
【问题描述】:

我正在尝试微调我的 MySQL 服务器,以便检查我的设置、分析慢查询日志并尽可能简化我的查询。

有时如果我的索引正确就足够了,有时则不然。我在某处读过(如果这是愚蠢的,请纠正我)比我需要的更多的索引会产生相同的效果,就像我没有任何索引一样。

多少索引就够了?你可以说这取决于数百个因素,但我很好奇如何清理我的mysql-slow.log 以减少服务器负载。

此外,我还看到了一些“有趣”的日志条目,如下所示:

# Query_time: 0  Lock_time: 0  Rows_sent: 22  Rows_examined: 44
SELECT * FROM `categories` ORDER BY `orderid` ASC;

有问题的表正好包含 22 行,索引设置在 orderid 中。为什么这个查询最终会出现在日志中?如果它只包含 22 行,为什么要检查 44 行?

【问题讨论】:

  • 我猜它做了一个排序,所以它以某种方式多次检查同一行:x
  • EXPLAIN SELECT * FROM categories ORDER BY orderid ASC 返回什么;
  • @R. Bemrose:如果我更正它会返回一个 Extra: Using filesort。也许这就是问题所在?

标签: mysql indexing performance logging


【解决方案1】:

“最佳”索引数量没有神奇的数字。基本规则是:为经常使用和/或需要快速运行的查询添加索引。

拥有“太多”索引不应减慢查询速度,但添加的每个索引都会增加少量时间来添加/更新数据库中的项目(因为它也会修改索引),并且少量空间。但是,如果您只是根据需要添加索引,这可能不是什么大问题。

【讨论】:

    【解决方案2】:

    作为一般规则,您应该在所有主键(您没有选择权)、所有外键以及您通常用于获取行的任何其他字段上都有索引。

    例如,如果我通常按用户名查找用户,我会将其编入索引,即使用户 ID 是主键。

    【讨论】:

      【解决方案3】:

      有多少索引完全取决于您运行的查询、正在执行的连接类型(如果有)、存储在表中的数据类型以及表有多大(以及许多其他因素)。确实没有确切的科学依据。在您的工具库中找出如何优化查询的最佳工具是explain。使用 explain 可以找出正在关闭的连接类型、可能使用的键、使用的键(如果有的话)以及连接中每个表检查了多少行。

      使用这些信息,您可以决定如何为您的表设置键和/或修改您的查询以提高它们的效率。解释的语法很简单。

      EXPLAIN SELECT * FROM `categories` ORDER BY `orderid` ASC;
      

      注意,说明 实际运行查询。因此,如果您使用它来调试需要 5 分钟才能运行的查询,解释仍然会非常快。

      添加索引时确实需要小心,因为它们确实会导致插入和更新速度变慢,并且在非常大的表上,这种性能影响可能会变得很明显。特别是如果同一张表用于大量读取。虽然添加大量索引通常不会影响查询的性能,但您仍然应该只将它们添加为 yo

      【讨论】:

        【解决方案4】:

        索引可以加快 SELECT 查询,但会减慢 INSERT/UPDATE/DELETE 查询,因为它们也需要更新索引,而不仅仅是行。

        这只是个人意见(我没有任何事实可以支持),但我认为如果有一个查询需要很长时间并且索引会加快它的速度 - 去吧!如果您添加了没有任何好处的索引(例如,没有查询会加快速度),则“太多”索引将是。例如,一个愚蠢的做法是“仅仅因为”在每一列上放置一个索引。

        【讨论】:

        • "一个愚蠢的做法是在每一列上放置一个索引,"只是因为"" - 这完全没问题,但我想尽可能多地消除慢日志条目。否则感谢您对插入/更新/删除的想法!
        【解决方案5】:

        索引的数量和做太多的线将取决于很多因素。在像“类别”表这样的小表上,您通常不需要或不需要索引,它实际上会损害性能。原因是读取索引需要 I/O(即时间),然后需要更多 I/O 和时间来检索与匹配行关联的记录。仅查询索引中包含的列时例外。

        在您的示例中,您正在检索所有列并且只有 22 行,并且只进行表扫描并对它们进行排序而不是使用索引可能会更快。优化器可能/应该这样做并忽略索引。如果是这种情况,那么索引只是占用空间而没有任何好处。如果您的“类别”表经常被访问,您可能需要考虑将其固定到内存中,以便 db 服务器保持可访问性,而不必一直访问磁盘。

        添加索引时,您需要平衡磁盘空间、查询性能以及更新和插入表的性能。与每天更新数百万次的表相比,您可以在静态且变化不大的表上使用更多索引。此时您将开始感受到索引维护的影响。但是,在您的环境中可接受的内容是并且只能由您和您的组织来确定。

        在进行分析时,请务必生成/更新您的表和索引统计信息,以便您可以放心进行准确的计算。

        【讨论】:

        • 谢谢!这对我来说是最清晰、最有帮助的答案!
        • 如何将表格“固定”到内存中?
        • 我怎样才能告诉 MySQL pin 一个表进入内存?
        • 一种方法是对表使用内存存储引擎。请注意,此方法有特定的用例和注意事项,通常您最好确保有足够的缓冲区空间来将最常访问的数据保存在数据库缓存中,同时使用 InnoDB 之类的引擎作为引擎。
        【解决方案6】:

        还请记住,MySQL 最多将使用 每个选择一个索引 语句(尽管如果您使用连接,它也可以为每个连接使用一个)。所以索引只是因为是浪费磁盘空间并且会减慢数据库的写入速度。如果您通常在两列上使用 where 语句,则创建一个包含这两列的索引,这将比单独索引一个快得多。

        【讨论】:

          猜你喜欢
          • 2015-05-16
          • 2023-04-02
          • 1970-01-01
          • 2010-09-23
          • 2010-12-18
          • 1970-01-01
          • 2023-04-11
          • 2020-05-23
          • 1970-01-01
          相关资源
          最近更新 更多