使用代码

Using bcp As New SqlBulkCopy(destConnection)
     bcp.DestinationTableName = "myOutputTable"
     bcp.BatchSize = 10000

     bcp.WriteToServer(reader)
End Using


其中reader是本质上是一个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


人工节流该过程以一次将少量数据运行到输出表中(大约
但是,如果我以较大的块(例如45k)运行(或让该进程运行整个200k),则碎片将变为99%+。

确切地说,如果我在39,773中运行,则得到而且,如果我调查在索引中分配的页面,则可以使用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%的碎片。

因此,问题是什么导致在较大数据块中运行时以这种方式建立索引?

最佳答案

没有更多数据很难说,但我敢打赌,您的时间戳是聚集索引,这是造成这种情况的原因。在发送到输出表之前,请尝试按此字段对数据进行排序。

10-04 11:21
查看更多