之前我已经在表格上创建了复合索引(为数学爱好者准备的索引),并假设它们是如何工作的。我只是好奇我的假设是否正确。
我假设当您列出索引的列顺序时,您还指定了索引的分组方式。例如,如果您有列a
,b
和,c
并且您以相同的顺序指定索引 ,a ASC
则结果索引本质上将是 中每个“组”的许多索引。b ASC
c ASC
a
它是否正确?如果不是,那么结果索引实际上会是什么样子?
复合索引与常规索引一样工作,只是它们具有多值键。
如果您在字段 (a,b,c) 上定义索引,则记录首先按 a 排序,然后是 b,然后是 c。
例子:
| A | B | C |
-------------
| 1 | 2 | 3 |
| 1 | 4 | 2 |
| 1 | 4 | 4 |
| 2 | 3 | 5 |
| 2 | 4 | 4 |
| 2 | 4 | 5 |
复合索引就像字典中的普通字母索引,但涵盖两个或多个字母,如下所示:
AA - page 1
AB - page 12
等等
表行首先按索引中的第一列排序,然后按第二列排序,以此类推。
当您按两列或第一列搜索时,它是可用的。如果你的索引是这样的:
AA - page 1
AB - page 12
…
AZ - page 245
BA - page 246
…
您可以使用它来搜索2
字母(= 2
表格中的列),或者像一个字母上的普通索引:
A - page 1
B - page 246
…
请注意,在字典的情况下,页面本身是按字母顺序排列的。这是一个CLUSTERED
索引的例子。
在普通的非CLUSTERED
索引中,对页面的引用是有序的,就像在历史书中一样:
Gaul, Alesia: pages 12, 56, 78
Gaul, Augustodonum Aeduorum: page 145
…
Gaul, Vellaunodunum: page 24
Egypt, Alexandria: pages 56, 194, 213, 234, 267
ORDER BY
当您有两个或更多列时,也可以使用复合索引。在这种情况下,一个DESC
子句可能会派上用场。
请参阅我的博客中有关DESC
在复合索引中使用子句的这篇文章:
最常见的索引实现使用 B 树来允许快速查找,以及相当快速的范围扫描。在这里解释太多了,但这里是关于B-trees的 Wikipedia 文章。你是对的,你在创建索引中声明的第一列将是生成的 B 树中的高阶列。
对高位列的搜索相当于范围扫描,而 B 树索引对于此类搜索非常有用。看到这一点的最简单方法是与图书馆中尚未转换为在线目录的旧卡片目录进行类比。
如果您要查找姓氏为“Clemens”的作者的所有卡片,您只需转到作者目录,并很快找到前面写着“CLE-CLI”的抽屉。那是正确的抽屉。现在你在那个抽屉里进行一种非正式的二分搜索,以快速找到上面写着“Clemens, Roger”或“Clemens, Samuel”的所有卡片。
但是假设您要查找名字为“Samuel”的作者的所有卡片。现在你已经上岸了,因为这些卡片并没有聚集在作者目录中的一个地方。数据库中的复合索引也会发生类似的现象。
不同的 DBMS 的优化器在检测索引范围扫描和准确估计其成本方面的聪明程度不同。并非所有索引都是 B 树。您必须阅读特定 DBMS 的文档才能获得真实信息。
不,结果索引将是单个索引,但具有复合键。
KeyX = A,B,C,D; KeyY = 1,2,3,4;
索引 KeyX, KeyY 实际上是:A1,A2,A3,B1,B3,C3,C4,D2
因此,如果您需要通过 KeyX和KeyY 找到某些东西 - 这将很快并且将使用单个索引。类似于 SELECT ... WHERE KeyX = "B" AND KeyY = 3。
但重要的是要理解: WHERE KeyX = ? 请求将使用该索引,而 WHERE KeyY = ? 根本不会使用这样的索引。