每天被截断的表的索引优化

Hik*_*ari 3 sql-server optimization clustered-index nonclustered-index query-performance

我在 SQL Server 2012 中有一堆表。

这些表由其他表提供。每天都有一些例程会截断(完全删除)它们并运行将结果插入其中的查询。它们就像静态视图,存储那些处理过的数据,以便更快地查询它们。

还有源表,每天接收数百万条新记录,这些不会被删除。

所有这些表都有一段时间会插入很多内容,而在一天的剩余时间里,它们只会被读取。

即使使用这些“静态视图”表,我认为我也可以提高整体性能。是否有处理这些行为的最佳实践?

对于第一种情况,我运行了一些基准测试,发现最好的性能来自对过滤最多的字段使用非聚集索引。我在截断之前删除这些索引并在插入后重新创建它们。删除和重新创建比重建更快,插入也更快。

我也应该保留 PK(没有语义意义)和聚集索引吗?我想如果没有索引,这些插入会更快,但是如果这些表没有 PK,我会有什么问题吗?它们从不明确使用。

我问这个是因为当我创建表并设置它的 PK 时

idBenchmark int NOT NULL IDENTITY (1,1) PRIMARY KEY
Run Code Online (Sandbox Code Playgroud)

聚集索引是自动创建的,具有随机名称,因此我无法删除并重新创建它。

Jon*_*des 6

继续并在导入数据时删除集群键。完成后INSERTs,首先创建集群键,然后创建 PK(如果它是非集群的),然后是任何剩余的索引。我此时正在运行这样的脚本,它所花费的时间大约是插入到完全索引的表中的一半。

在加载数据时没有集群键没有问题。如果可能的话,我建议您以与聚类相同的顺序导入数据;这将减少在数据聚集时对数据进行混洗的需要。如果您使用的是任意IDENTITY列,我建议您重新考虑;可能有更好的聚类候选者(或者您甚至可能不需要聚类键)。

在加载数据时没有 PK 没有问题。这对于保持参照完整性和为您的索引提供一个狭窄的目标是最重要的;当您批量加载数据时,两者都不适用,假设您相信您的数据不包含重复项。

重复也不总是魔鬼,在批量加载后删除它们可能比在前端构建以其他方式重复删除的进程更快。

我的偏好是首先将所有丑陋的原始数据拉入堆表中,然后在将其复制到新表之前进行 SQL 清理。也许那只是因为我是一个 SQL 人,一切对我来说都像是钉子,但 SQL针对基于集合的操作进行了优化。另一方面,如果数据量很大,您可能需要在通过 SSIS 或其他方式导入数据时基于 RBAR 进行转换和清理。

我还建议ALTER TABLE在您的CREATE TABLE. 这会提醒您做出明确的选择(包括是否在 PK 上聚类),将其放在其他索引声明旁边,并允许您为其指定一个非随机名称。