MySQL索引 - 有多少就足够了?

时间:2009-08-14 13:34:16

标签: mysql indexing performance logging

我正在尝试微调我的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中的索引集。为什么这个查询毕竟出现在日志中?为什么检查44行,如果它只包含22?

6 个答案:

答案 0 :(得分:22)

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

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

添加索引时,需要平衡磁盘空间,查询性能以及更新和插入表的性能。对于每天有数百万次更新的表,您可以在静态表上获得更多索引,并且不会发生太大变化。您将在那时开始感受索引维护的影响。您的环境中可接受的是,您只能由您和您的组织决定。

进行分析时,请务必生成/更新表和索引统计信息,以确保准确计算。

答案 1 :(得分:13)

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

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

答案 2 :(得分:6)

有多少索引完全取决于您运行的查询,正在进行的连接类型(如果有),表中存储的数据类型以及表的大小(以及许多其他因素)。它真的没有确切的科学。您的工具库中用于确定如何优化查询的最佳工具是explain。使用说明,您可以找出正在使用哪种连接,可以使用哪些键以及使用了哪个键(如果有)以及为连接中的每个表检查了多少行。

使用此信息,您可以决定如何键入表格和/或修改查询以提高查询效率。解释的语法非常简单。

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

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

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

答案 3 :(得分:5)

还要记住,MySQL每个选择语句最多使用一个索引(尽管如果使用连接,它也可以为每个连接使用一个)。因此仅仅因为索引就浪费了磁盘空间,并且会降低数据库的写入速度。如果你经常在两列上使用where语句,那么做一个包含这两列的索引,它将比仅仅索引一列快得多。

答案 4 :(得分:4)

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

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

答案 5 :(得分:3)

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

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