代码之家  ›  专栏  ›  技术社区  ›  Andreas Bonini

多个和单个索引

  •  30
  • Andreas Bonini  · 技术社区  · 15 年前

    我有点不好意思问这个问题,因为我已经和MySQL一起工作多年了,但是哦,好吧。

    我有一张有两块地的桌子, a b .我将对它运行以下查询:

    • 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 回复  |  直到 15 年前
        1
  •  28
  •   Andreas Bonini    15 年前

    是的,至少有一种情况要慢得多。如果只定义以下索引:

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

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

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

        2
  •  22
  •   Quassnoi    15 年前

    仅仅存在一个指数就很难减缓 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 = 1 b = 1 ,相当适合 A=1,B=1

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

    优秀的 A=1,B=1 几乎非常适合 A=1 可怜的 B=1

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

    非常适合所有三个查询。

        3
  •  4
  •   jjacka    15 年前

    SQL将选择最能覆盖查询的索引。 A、B上的索引将同时包含案例1和3的查询,但不包括2的查询(因为主索引列是A)

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

    ALTER TABLE ... ADD INDEX (a, b); ALTER TABLE ... ADD INDEX (b)
    
        4
  •  0
  •   netricate    15 年前

    例如,您的索引集3是最佳的。MySQL将为单列WHERE子句选择单个A和B索引,并为A&B WHERE子句使用复合索引。