多个和单个索引

Tho*_*ini 31 mysql sql 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);

谢谢(请注意,我们正在讨论非唯一索引)

Dan*_*llo 28

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

ALTER TABLE ... ADD INDEX (a, b);
Run Code Online (Sandbox Code Playgroud)

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

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

  • 使用配置#3而不是#1是否有任何优势? (6认同)
  • 是的,可能会有优势.当查询中的所有数据都保存在索引本身内时,复合索引可以成为覆盖索引.一般来说,`SELECT A,B FROM ... WHERE A = 1;`,如果在`(A,B)`上使用复合索引,会更快,因为查询不需要从表中获取任何数据.数据已经在索引中. (6认同)

Qua*_*noi 22

仅存在索引会使SELECT查询变慢,这是不太可能的:它不会被使用.

从理论上讲,优化器可能会错误地选择更长的索引(a, b)而不是一个on (a)来提供仅搜索的查询a.

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

更新:

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

(a, b); (b)
Run Code Online (Sandbox Code Playgroud)

要么

(b, a); (a)
Run Code Online (Sandbox Code Playgroud)

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

(a); (b)
Run Code Online (Sandbox Code Playgroud)

a = 1 AND b = 1尽管程度低于上述任何解决方案,但也会加快查询速度.

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

更新2:

好像我终于理解了你的问题:)

ALTER TABLE ... ADD INDEX (a); ALTER TABLE ... ADD INDEX (b);
Run Code Online (Sandbox Code Playgroud)

非常适合a = 1b = 1合理的a = 1 AND b = 1

ALTER TABLE ... ADD INDEX (a, b);
Run Code Online (Sandbox Code Playgroud)

非常适合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);
Run Code Online (Sandbox Code Playgroud)

非常适合所有三个查询.