使用SqlBulkCopy在数据库之间移动大量数据时,为什么会出现高碎片?

时间:2016-05-17 15:48:27

标签: sql sql-server indexing sqlbulkcopy

使用代码

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%。

所以,问题是当在更大的数据块中运行时,是什么原因导致索引被构建?

2 个答案:

答案 0 :(得分:2)

在没有更多数据的情况下很难分辨,但我敢打赌,你的时间戳是聚集索引会导致这种情况。尝试在发送到输出表之前按此字段对数据进行排序。

答案 1 :(得分:1)

对于对此问题的结果感兴趣的任何人。

我发现碎片是由表格中可变数量的重复造成的。

要解释一下,作为NON-UNIQUE中的索引是可能的,并且确实是TimeStamps重复的情况。但是如果这些组的大小都相同,那么例如,每个时间戳通过该文件一直有7行,那么碎片将是&lt;完成时为1%。但是,如果表格更加可变,那么碎片化将会迅速增加。例如,如果有每个时间戳有7行的数据块,那么一些有6个,有些有5个等碎片将超过99%,我们看到这个交错(如问题中所述)。