2016-05-17 2 views
4

Использование кодаПочему я получаю высокую фрагментацию при использовании SqlBulkCopy для перемещения больших объемов данных между базами данных?

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

    bcp.WriteToServer(reader) 
End Using 

где читатель является по существу IDataReader, который считывает в таблице, содержащий 200k строк или около того.

вход таблица выглядит следующим образом

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 

Искусственно дросселирования процесс для запуска небольших (МОГ) количество данных в выходной таблице, в то время (около < 35к) приведет к фрагментации < 5% и все в порядке.

Но если я запускаю более крупный кусок, скажем, 45k (или пусть весь процесс работает 200k), фрагментация становится 99% +.

Если быть точным, если я бегу в 39 773, то получаю < 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

Вы также можете загружать его в промежуточный стол и сортировать его перед тем, как вставлять его в реальную таблицу. –

1

Для всех, кто заинтересован в исходе этой проблемы.

Я обнаружил, что фрагментация вызвана переменным количеством дубликатов в таблице.

Чтобы объяснить, как Индекс в НЕ-УНИКАЛЬНО, возможно, и действительно, так, что TimeStamps дублируются. Но если группы имеют одинаковый размер, то есть, например, 7 строк на метку времени последовательно через файл, тогда фрагментация будет < 1% при завершении. Но, если бы таблица была более переменной, фрагментация быстро увеличивалась. Например, если бы были фрагменты данных, в которых было 7 строк на метку времени, то некоторые из них с 6, некоторые с фрагментацией из 5 и т. Д. Были бы более 99% с этим чередованием, которое мы видим (как описано в вопросе).

Смежные вопросы