使用代码
Using bcp As New SqlBulkCopy(destConnection)
bcp.DestinationTableName = "myOutputTable"
bcp.BatchSize = 10000
bcp.WriteToServer(reader)
End Using
读者本质上是一个读取表格的IDataReader,包含20万行左右。
输入表如下所示
CREATE TABLE [dbo].[MyTable](
[TagIndex] [SMALLINT] NOT NULL,
[TimeStamp] [DATETIME] NOT NULL,
[RawQuality] [SMALLINT] NOT NULL,
[ValQuality] [SMALLINT] NOT NULL,
[Sigma] [REAL] NULL,
[Corrected] [REAL] NULL,
[Raw] [REAL] NULL,
[Delta] [REAL] NULL,
[Mean] [REAL] NULL,
[ScadaTimestamp] [DATETIME] NOT NULL
) ON [PRIMARY
由TimeStamp订购。
输出表具有相同的结构并具有以下索引(并且在过程开始时为空)。
CREATE CLUSTERED INDEX [MyOutputTable_Index] ON [dbo].[MyOutputTable]
(
[TimeStamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO
人为地限制进程以一次(大约<35k)将少量(数据)量的数据运行到输出表中将导致&lt; 5%,一切都很好。
但如果我运行更大的块,比如说45k,(或者让整个过程运行整个200k),碎片就会变成99%+。
准确地说,如果我在39,773跑,我得到&lt; 5%的碎片,但我在39,774运行,我得到99%的碎片。 如果我调查在索引中分配的页面,我会使用DBCC PAGE看到以下内容。
FileId PageId Row Level ChildFileId ChildPageId TimeStamp (key)
1 18937 0 1 1 18906 2015-10-22 01:37:32.497
1 18937 1 1 1 18686 2015-10-22 01:38:12.497
1 18937 2 1 1 18907 2015-10-22 01:38:47.497
1 18937 3 1 1 18687 2015-10-22 01:39:27.497
1 18937 4 1 1 18908 2015-10-22 01:40:02.497
1 18937 5 1 1 18688 2015-10-22 01:40:42.497
1 18937 6 1 1 18909 2015-10-22 01:41:17.497
1 18937 7 1 1 18689 2015-10-22 01:41:57.497
1 18937 8 1 1 18910 2015-10-22 01:42:32.497
查看ChildPageId列,我们可以看到这些数字不会连续运行。
例如,18906之后是18686,之后是18907,系列开始18686与18906开始的系列交错,导致碎片超过99%。
所以,问题是当在更大的数据块中运行时,是什么原因导致索引被构建?
答案 0 :(得分:2)
在没有更多数据的情况下很难分辨,但我敢打赌,你的时间戳是聚集索引会导致这种情况。尝试在发送到输出表之前按此字段对数据进行排序。
答案 1 :(得分:1)
对于对此问题的结果感兴趣的任何人。
我发现碎片是由表格中可变数量的重复造成的。
要解释一下,作为NON-UNIQUE中的索引是可能的,并且确实是TimeStamps重复的情况。但是如果这些组的大小都相同,那么例如,每个时间戳通过该文件一直有7行,那么碎片将是&lt;完成时为1%。但是,如果表格更加可变,那么碎片化将会迅速增加。例如,如果有每个时间戳有7行的数据块,那么一些有6个,有些有5个等碎片将超过99%,我们看到这个交错(如问题中所述)。