这是按照discussion with @Catcall 测试聚集表上covering 二级索引的大小和性能特征的尝试。
所有测试均在 MS SQL Server 2008 R2 Express 上完成(在一个功率相当不足的 VM 内)。
尺寸
首先,我用二级索引创建了一个聚集表,并用一些测试数据填充它:
CREATE TABLE THE_TABLE (
FIELD1 int,
FIELD2 int NOT NULL,
CONSTRAINT THE_TABLE_PK PRIMARY KEY (FIELD1)
);
CREATE INDEX THE_TABLE_IE1 ON THE_TABLE (FIELD2) INCLUDE (FIELD1);
DECLARE @COUNT int = 1;
WHILE @COUNT <= 1000000 BEGIN
INSERT INTO THE_TABLE (FIELD1, FIELD2) VALUES (@COUNT, @COUNT);
SET @COUNT = @COUNT + 1;
END;
EXEC sp_spaceused 'THE_TABLE';
最后一行给了我以下结果...
name rows reserved data index_size unused
THE_TABLE 1000000 27856 KB 16808 KB 11008 KB 40 KB
所以,索引的 B-Tree (11008 KB) 实际上小于表的 B-Tree (16808 KB)。
速度
我在表中的数据范围内生成了一个随机数,然后将其作为从表中选择整行的标准。重复 10000 次,测量总时间:
DECLARE @I int = 1;
DECLARE @F1 int;
DECLARE @F2 int;
DECLARE @END_TIME DATETIME2;
DECLARE @START_TIME DATETIME2 = SYSDATETIME();
WHILE @I <= 10000 BEGIN
SELECT @F1 = FIELD1, @F2 = FIELD2
FROM THE_TABLE
WHERE FIELD1 = (SELECT CEILING(RAND() * 1000000));
SET @I = @I + 1;
END;
SET @END_TIME = SYSDATETIME();
SELECT DATEDIFF(millisecond, @START_TIME, @END_TIME);
最后一行产生的平均时间(10 次测量)为 181.3 毫秒。
当我将查询条件改为:WHERE FIELD2 = ...,所以使用二级索引,平均时间为195.2ms。
执行计划:
因此(在 PK 上选择与在覆盖二级索引上进行选择)似乎是相似的。对于更大量的数据,我怀疑二级索引可能会稍微快一些(因为它看起来更紧凑,因此对缓存友好),但我在测试中还没有达到这一点。
字符串测量
使用 varchar(50) 作为 FIELD1 和 FIELD2 的类型并插入长度在 22 到 28 个字符之间变化的字符串会产生类似的结果。
尺寸是:
name rows reserved data index_size unused
THE_TABLE 1000000 208144 KB 112424 KB 95632 KB 88 KB
平均时间是:搜索FIELD1 254.7 毫秒和 296.9 毫秒 FIELD2。
结论
如果一个聚簇表有一个覆盖二级索引,该索引将具有类似于表本身的空间和时间特征(可能稍微慢一些,但不会慢很多)。如果有效,您将拥有两个 B 树,它们对数据进行不同的排序,但在其他方面非常相似,从而实现拥有“第二个集群”的目标。