【发布时间】: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
何时需要以下内容:
create index i_t_a_b on t(a,b);
create index i_t_b_a on t(b,a);
【问题讨论】:
标签: mysql covering-index
当您想要最大的检索速度并且在连接或 where 条件中都有两列时,但有时列 a 具有更高的选择性,有时列 b 具有更高的选择性,并且您希望从单个索引中利用这一事实。
另外我认为你的数据大小/机器性能的比率应该相当高,同时你必须(猜测)愿意将任何改进称为必要性(即使只有几个百分比)。
不过,经验告诉我们,事情取决于很多因素;对于特定的 RDBMS 和应用程序环境,您最好运行自己的基准测试。
编辑:
综合指数的进一步解释。
来自wikipedia:
“列在索引定义中的列出顺序很重要。可以仅使用第一个索引列来检索一组行标识符。但是,这是不可能的或仅使用第二个或更大的索引列有效地(在大多数数据库上)检索行标识符集。
例如,想象一个电话簿,它首先按城市,然后按姓氏,然后按名字。如果您获得了城市,您可以轻松提取该城市的所有电话号码列表。然而,在这个电话簿中查找给定姓氏的所有电话号码将非常繁琐。您必须在每个城市的部分中查找具有该姓氏的条目。”
Wikipedia 的解释可能过于简化,但它为您提供了基本概念(作为类比,请记住电话簿通常具有聚集索引,而不是您的通用数据库索引)。
根据索引的大小、数据结构的大小、可用内存和索引第一列的选择性,使用错误排序的索引可能比使用表扫描更便宜。
啊,只是想到了一个更好的类比与您正在寻找的示例 想象一本不错的教科书,它会有包含章节和子章节的目录以及它们所在的页面数(这是一个非聚集索引,它保存指向数据记录的指针 - 页面)。 现在假设教科书是基于 SQL-92 标准的,那么 TOC 中的大部分术语都是 SQL 术语(保持这个假设)。 您还会在本书的末尾有另一个索引,它将按字母顺序(假设主要章节名称)和页码列出所有有趣的术语。
对于诸如 '告诉我所有出现 DISTINCT 的章节'你会使用第二个索引。 (因为后面字段的选择性高)
对于诸如 '告诉我出现在第一章下的术语的数量'你会使用 TOC
所以对于诸如 '在 DML 章节中描述了 SELECT 吗?您可以使用任何一个索引。 (因为这两个领域的选择性都很高) 但是,如果 DML 本身的 TOC 是 3 页长并且索引中的 SELECT 条目只有 15 行,您可能会转到第二行,这就是您从两个索引中受益的示例。
现在,如果您认为这太过分了,请考虑使用已扫描的国会图书馆数据库。 :)
正如我之前所说,所有的计划都很好,但最后还是要运行自己的基准测试。
【讨论】:
我认为没有任何实际情况需要您这样做。
当您的表有更多列时可能有意义,a 和 b 不是唯一的,并且您需要以下两个查询的高性能:
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_a 的8 和9 才能找到所有带有a=1 的行。这仍然比全表扫描快得多(也必须读取所有x),但不如使用i_t_a_b 快。
【讨论】:
b=1,反之亦然