多个和单个索引

时间:2010-01-28 15:33:45

标签: sql mysql database indexing

自从我使用MySQL多年以来,我有点羞于问这个问题,但是很好。

我有一个包含两个字段的表,ab。我将在其上运行以下查询:

  • SELECT * FROM ... WHERE A = 1;
  • SELECT * FROM ... WHERE B = 1;
  • SELECT * FROM ... WHERE A = 1 AND B = 1;

从性能的角度来看,对于至少一个查询,至少是以下一种索引配置?如果是,请详细说明。

  1. ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b);
  2. ALTER TABLE ... ADD INDEX (a, b);
  3. ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); ALTER TABLE ... ADD INDEX (a, b);
  4. 谢谢(请注意,我们正在讨论非唯一索引)

4 个答案:

答案 0 :(得分:28)

是的,至少有一个案例相当慢。如果您只定义以下索引:

ALTER TABLE ... ADD INDEX (a, b);

...然后查询SELECT * FROM ... WHERE B = 1;将不会使用该索引。

使用复合键创建索引时,键的列顺序很重要。建议尝试对键中的列进行排序以增强选择性,最左侧的键选择最多的列。如果您不这样做,并将非选择性列作为密钥的第一部分,则可能根本不使用索引。 (来源:Tips on Optimizing SQL Server Composite Index

答案 1 :(得分:22)

仅仅存在索引会减慢SELECT查询的速度是不太可能的:它不会被使用。

理论上,优化程序可能会错误地选择(a, b)上的更长索引而不是(a)上的索引来提供仅搜索a的查询。

在实践中,我从未见过它:MySQL通常会出现相反的错误,当存在较长的索引时会采用较短的索引。

<强>更新

在您的情况下,以下任一配置都足以满足所有查询:

(a, b); (b)

(b, a); (a)

MySQL也可以使用两个单独的索引index_intersect,因此创建这些索引

(a); (b)

也会加快a = 1 AND b = 1的查询速度,但程度可能低于上述任何解决方案。

您可能还想在我的博客中阅读这篇文章:

更新2:

似乎我终于理解了你的问题:)

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b);

非常适合a = 1b = 1,相当适合a = 1 AND b = 1

ALTER TABLE ... ADD INDEX (a, b);

非常适合a = 1 AND b = 1,几乎非常适合a = 1,差b = 1

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b); ALTER TABLE ... ADD INDEX (a, b);

非常适合所有三个查询。

答案 2 :(得分:4)

SQL将选择最适合查询的索引。 A,B的索引将涵盖案例1和3的查询,但不包括2(因为主索引列是A)

因此,为了涵盖所有三个查询,您需要两个索引:

ALTER TABLE ... ADD INDEX (a, b); ALTER TABLE ... ADD INDEX (b)

答案 3 :(得分:0)

对于示例,您有索引集#3是最佳的。 Mysql将为单列where子句选择单个A和B索引,并使用复合索引作为A&amp; B where where。