我们的供应商几乎在整个数据库的每一列上都更改了列宽.该数据库大约有7TB,9000个表.我们正在尝试在具有55亿行的表上创建索引.在供应商升级之前,我们可以在2小时内创建索引.现在需要几天时间.他们所做的是将任何varchar(xx)大小增加到varchar(256).所以大多数列过去都是varchar(18)或varchar(75)等.
无论如何,主键由6列组成,组合宽度为126个字符.现在升级后,主键为1283个字符,违反了SQL Server限制为900个字符.整个表的列宽从总组合varchar计数1049变为总组合varchar计数4009.
数据没有增加,表格不会占用比所有列宽增加之前更多的“空间”,但是创建像索引一样简单的表现现在花费了不合理的时间.
任何人都可以解释为什么创建和索引需要花费更长的时间来完成唯一的事情就是增加列的大小?
我们尝试创建的索引是非聚簇的,因为pk是聚簇索引.在多次尝试创建索引后,我们放弃了.我认为它没有完成就运行了4到5天.
我通过获取文件系统快照并在更安静的服务器上启动数据库,在非生产环境中尝试了这一点.
解决方法
Remus帮助指出VARCHAR列的最大长度会影响估计的行大小,因此会影响SQL Server提供的内存授权.
我试图做更多的研究,以扩展他的答案中的“从事物级联”这一部分.我没有完整或简明的解释,但这是我找到的.
Repro脚本
I created a full script生成一个假数据集,在我的机器上,VARCHAR(256)版本的索引创建大约需要10倍.使用的数据完全相同,但第一个表使用实际的最大长度18,75,9,15,123和5,而所有列在第二个表中使用最大长度256.
键入原始表
在这里,我们看到原始查询在大约20秒内完成,逻辑读取等于~1.5GB的表大小(195K页,每页8K).
-- CPU time = 37674 ms,elapsed time = 19206 ms. -- Table 'testVarchar'. Scan count 9,logical reads 194490,physical reads 0 CREATE CLUSTERED INDEX IX_testVarchar ON dbo.testVarchar (s1,s2,s3,s4) WITH (MAXDOP = 8) -- Same as my global MAXDOP,but just being explicit GO
键入VARCHAR(256)表
对于VARCHAR(256)表,我们看到经过的时间已经大大增加.
有趣的是,CPU时间和逻辑读取都没有增加.这是有道理的,因为该表具有完全相同的数据,但它不能解释为什么经过的时间要慢得多.
-- CPU time = 33212 ms,elapsed time = 263134 ms. -- Table 'testVarchar256'. Scan count 9,logical reads 194491 CREATE CLUSTERED INDEX IX_testVarchar256 ON dbo.testVarchar256 (s1,but just being explicit GO
I / O和等待统计:原始
如果我们捕获更多细节(使用p_perfMon,a procedure that I wrote),我们可以看到绝大多数I / O都是在LOG文件上执行的.我们在实际的ROWS(主数据文件)上看到相对适度的I / O量,主要的等待类型是LATCH_EX,表示内存中的页面争用.
我们还可以看到我的旋转磁盘介于“坏”和“令人震惊的坏”之间,according to Paul Randal