SQL 临时表:主键聚集或堆

6 performance database-design sql-server etl sql-server-2016 performance-tuning

我们正在使用传统的平面 txt 文件并将它们插入到带有 SSIS 的阶段表中。问题出现了表是否应该具有主聚集键索引。这是没有转换的直接平面文件导入。

create table dbo.CustomerTransaction
(
     CustomerName varchar(255),
     PurchaseLocation varchar(255),
     Productid  int,
     AmountSold float,
     CustomerAddress varchar(50)
)

create table dbo.CustomerTransaction
(
     -- discussion for adding this column
     CustomerTransactionId int primary key clustered identity(1,1) 

     CustomerName varchar(255),
     PurchaseLocation varchar(255),
     Productid  int,
     AmountSold float,
     CustomerAddress varchar(50)
)

-- both tables have nonclustered indexes
create nonclustered index idx_ProductId on dbo.CustomerTransaction(ProductId)
create nonclustered index idx_CustomerAddress on dbo.CustomerTransaction(CustomerAddress)

-- Actually have more indexes, tables above are just for sample 
Run Code Online (Sandbox Code Playgroud)

1)在ETL之前,临时表被截断。没有删除和更新。仅插入。

truncate table dbo.[CustomerTransaction]
Run Code Online (Sandbox Code Playgroud)

2)然后在ETL之前禁用所有索引。

alter index all on dbo.[CustomerTransaction] DISABLE
Run Code Online (Sandbox Code Playgroud)

3)我们用默认的fast load进行SSIS数据流,我读的相当于bulk insert。这里没有发生任何转换。

4) 然后在导入完成后重新启用所有索引。

alter index all on dbo.[CustomerTransaction] REBUILD
Run Code Online (Sandbox Code Playgroud)

5) 然后在 join 和 where 子句上选择临时表,并将其放入数据仓库。这就是为什么我们有非聚集索引。加载数据仓库后,我们截断临时表。

我们听说 ETL 阶段表与堆一样好。但是,还可以了解堆的碎片化和性能问题。阅读以下所有文章

我正在阅读相互矛盾的意见。有人说二叉树集群是导入 ETL 的维护难题。其他人说堆存在碎片化的性能问题。我们的性能测试没有显示出太大的差异,但我们的数据可能会在以后发生变化。所以我们需要做出一个好的设计决策。

https://sqlsunday.com/2016/09/01/compelling-case-for-heaps/

https://www.mssqltips.com/sqlservertip/4961/sql-server-insert-performance-for-clustered-indexes-vs-heap-tables/

http://kejser.org/clustered-indexes-vs-heaps/

https://www.red-gate.com/simple-talk/sql/database-administration/sql-server-heaps-and-their-fragmentation/

我们知道拥有标识的一个很好的理由是行标签,但问题主要是关于内部结构和性能。

Rob*_*ley 5

拥有标识列并不强制您将其用作聚集索引键。

你是对的,堆在这里工作得很好。我认为 Thomas Kejser 是该主题的权威,并且您将他列为您的资源之一很好。

至于堆中的碎片-仅在插入时不会发生。

编辑:阅读这篇关于并行插入的文章,并注意堆和聚集索引之间的比较。https://blogs.msdn.microsoft.com/sqlcat/2016/07/21/real-world-parallel-insert-what-else-you-need-to-know/


Joe*_*ish 2

我们遇到了类似的情况,最近将临时表从聚集索引切换到堆。对我们来说,第一个大优势是我们希望允许并发 SSIS 加载到同一个临时表中。您可以使用聚集索引来做到这一点,但您可能会遇到很多阻塞,尤其是使用标识列时。第二大优势是减少加载暂存表的开销。我们发现,与聚集索引相比,堆上的加载速度要快得多。

我们的性能测试并没有显示出太大的差异,但是我们的数据稍后可能会发生变化。所以我们需要做出一个好的设计决策。

你确定这是真的吗?在这个问题中,您说您在加载之前截断了临时表。如果加载过程的某些部分发生变化,那么在表为空时添加或删除聚集索引应该非常简单。不涉及数据移动。听起来您不会从聚集索引中获得任何好处,因此我会尝试将其作为堆并监视性能。