【问题标题】:Does compound index have direction in MySQL?复合索引在 MySQL 中有方向吗?
【发布时间】:2010-03-23 13:58:01
【问题描述】:

何时需要以下内容:

create index i_t_a_b on t(a,b);

create index i_t_b_a on t(b,a);

【问题讨论】:

    标签: mysql covering-index


    【解决方案1】:

    当您想要最大的检索速度并且在连接或 where 条件中都有两列时,但有时列 a 具有更高的选择性,有时列 b 具有更高的选择性,并且您希望从单个索引中利用这一事实。

    另外我认为你的数据大小/机器性能的比率应该相当高,同时你必须(猜测)愿意将任何改进称为必要性(即使只有几个百分比)。

    不过,经验告诉我们,事情取决于很多因素;对于特定的 RDBMS 和应用程序环境,您最好运行自己的基准测试。

    编辑: 综合指数的进一步解释。 来自wikipedia:
    “列在索引定义中的列出顺序很重要。可以仅使用第一个索引列来检索一组行标识符。但是,这是不可能的或仅使用第二个或更大的索引列有效地(在大多数数据库上)检索行标识符集。
    例如,想象一个电话簿,它首先按城市,然后按姓氏,然后按名字。如果您获得了城市,您可以轻松提取该城市的所有电话号码列表。然而,在这个电话簿中查找给定姓氏的所有电话号码将非常繁琐。您必须在每个城市的部分中查找具有该姓氏的条目。”

    Wikipedia 的解释可能过于简化,但它为您提供了基本概念(作为类比,请记住电话簿通常具有聚集索引,而不是您的通用数据库索引)。

    根据索引的大小、数据结构的大小、可用内存和索引第一列的选择性,使用错误排序的索引可能比使用表扫描更便宜。

    啊,只是想到了一个更好的类比与您正在寻找的示例 想象一本不错的教科书,它会有包含章节和子章节的目录以及它们所在的页面数(这是一个非聚集索引,它保存指向数据记录的指针 - 页面)。 现在假设教科书是基于 SQL-92 标准的,那么 TOC 中的大部分术语都是 SQL 术语(保持这个假设)。 您还会在本书的末尾有另一个索引,它将按字母顺序(假设主要章节名称)和页码列出所有有趣的术语。

    对于诸如 '告诉我所有出现 DISTINCT 的章节'你会使用第二个索引。 (因为后面字段的选择性高)

    对于诸如 '告诉我出现在第一章下的术语的数量'你会使用 TOC

    所以对于诸如 '在 DML 章节中描述了 SELECT 吗?您可以使用任何一个索引。 (因为这两个领域的选择性都很高) 但是,如果 DML 本身的 TOC 是 3 页长并且索引中的 SELECT 条目只有 15 行,您可能会转到第二行,这就是您从两个索引中受益的示例。

    现在,如果您认为这太过分了,请考虑使用已扫描的国会图书馆数据库。 :)

    正如我之前所说,所有的计划都很好,但最后还是要运行自己的基准测试。

    【讨论】:

    • +1:很好的解释。也请随意对我的答案进行投票 - 如果您同意:)
    【解决方案2】:

    我认为没有任何实际情况需要您这样做。

    当您的表有更多列时可能有意义,ab 不是唯一的,并且您需要以下两个查询的高性能:

    Select Max(b) From t Where a=1  --# Would use i_t_a_b
    

    Select Max(a) From t Where b=1  --# Would use i_t_b_a
    

    假设您的表格如下所示:

    a  b  c  d  e
    -  -  -  -  -
    0  8  x  x  x
    0  9  x  x  x
    1  8  x  x  x
    1  9  x  x  x
    

    i_t_a_b 看起来像这样:

    0
      8
      9
    1
      8
      9
    

    i_t_b_a 看起来像这样:

    8
      0
      1
    9
      0
      1
    

    Select Max(b) From t Where a=1
    

    必须深入研究i_t_b_a89 才能找到所有带有a=1 的行。这仍然比全表扫描快得多(也必须读取所有x),但不如使用i_t_a_b 快。

    【讨论】:

    • 我做了一个测试,发现i_t_a_b也可以用于b=1,反之亦然
    • @symfony:是的,它可以使用,它比对表进行全扫描更好,但是对于 b=1,i_t_b_a 的性能要好于 i_t_a_b
    • 你能对此做一些分析吗?虽然直觉上听起来很合理
    • @symfony:我试图添加一个简化的解释我的意思。
    • 我认为这并不重要,因为 MySQL 应该足够聪明地决定从索引的哪一侧扫描
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多