Pourquoi la fragmentation est-elle élevée lorsque j'utilise SqlBulkCopy pour déplacer de grandes quantités de données entre bases de données?

indexing sql sqlbulkcopy sql-server

Question

En utilisant le code

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

     bcp.WriteToServer(reader)
End Using

Où reader est essentiellement un IDataReader qui lit dans une table, contenant environ 200 000 lignes.

La table d'entrée ressemble à ceci

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

Et est commandé par TimeStamp.

La table en sortie est de la même structure et possède l'index suivant (et est vide au début du processus).

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

Limiter artificiellement le processus pour exécuter de petites quantités (ish) de données dans la table de sortie à la fois (environ <35 000 $) entraînera une fragmentation de <5% et tout va bien.

Mais si je cours dans une plus grande portion, disons 45k (ou laissez le processus exécuter les 200k entiers), la fragmentation devient 99% +.

Pour être précis, si je cours en 39 773, la fragmentation est <5%, mais en 39 774, la fragmentation est de 99%. Et si j’étudie les pages allouées dans l’index, je vois ce qui suit avec 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

En regardant la colonne ChildPageId, nous pouvons voir que les nombres ne sont pas exécutés de manière consécutive.

Par exemple, 18906 est suivi de 18686, suivi de 18907, la série commençant en 18686 étant entrelacée avec la série commençant par 18906, provoquant une fragmentation supérieure à 99%.

La question est donc de savoir ce qui provoque la construction de l'index de cette manière lors de l'exécution de gros morceaux de données.

Réponse populaire

Il est difficile de dire sans plus de données, mais je parie que votre horodatage est un index clusterisé. Essayez de trier les données selon ce champ avant de les envoyer à la table en sortie.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi