J'ai donc un processus d'insertion en bloc simple pour prendre les données de notre table de transfert et les déplacer dans notre datamart.
Le processus est une tâche de flux de données simple avec des paramètres par défaut pour "Lignes par lot" et les options sont "tablock" et "no check constraint".
La table est assez grande. 587 162 986 avec une taille de données de 201 Go et 49 Go d'espace d'index. L'index cluster de la table est.
CREATE CLUSTERED INDEX ImageData ON dbo.ImageData
(
DOC_ID ASC,
ACCT_NUM ASC,
MasterID ASC
)
Et la clé primaire est:
ALTER TABLE dbo.ImageData
ADD CONSTRAINT ImageData
PRIMARY KEY NONCLUSTERED
(
ImageID ASC,
DT_CRTE_DOC ASC
)
Maintenant, nous avons eu un problème où BULK INSERT
via SSIS fonctionne incroyablement lentement. 1 heure pour insérer un million de lignes. La requête qui remplit la table est déjà triée et la requête à remplir prend moins d'une minute pour s'exécuter.
Lorsque le processus est en cours d'exécution, je peux voir la requête en attente sur l'insertion BULK qui prend entre 5 et 20 secondes et affiche un type d'attente de PAGEIOLATCH_EX
. Le processus ne peut traiter qu'un INSERT
millier de lignes à la fois.
Hier, lors du test de ce processus par rapport à mon environnement UAT, je rencontrais le même problème. J'exécutais le processus plusieurs fois et essayais de déterminer la cause première de cette insertion lente. Puis tout d'un coup, il a commencé à fonctionner en moins de 5 minutes. Je l'ai donc couru quelques fois de plus avec le même résultat. De plus, le nombre d'inserts en vrac qui attendaient pendant 5 secondes ou plus a chuté de centaines à environ 4.
Maintenant, cela laisse perplexe parce que ce n'est pas comme si nous avions eu une énorme baisse d'activité.
Le processeur pendant la durée est faible.
Les moments où il est plus lent semblent avoir moins d'attentes sur le disque.
La latence du disque augmente en fait pendant la période d'exécution du processus en moins de 5 minutes.
Et l'IO était beaucoup plus faible pendant les périodes où ce processus fonctionnait mal.
J'ai déjà vérifié et il n'y a pas eu de croissance de fichiers car les fichiers ne sont pleins qu'à 70%. Il reste encore 50% au fichier journal. La base de données est en mode de récupération simple. DB n'a qu'un seul groupe de fichiers mais est réparti sur 4 fichiers.
Donc, je me demande A: pourquoi voyais-je des temps d'attente aussi longs sur ces encarts en vrac. B: quelle sorte de magie s'est produite qui l'a rendu plus rapide?
Note de côté. Il fonctionne à nouveau comme de la merde aujourd'hui.
MISE À JOUR, il est actuellement partitionné. Cependant, cela se fait dans une méthode qui est au mieux idiote.
CREATE PARTITION SCHEME [ps_Image] AS PARTITION [pf_Image]
TO ([FG_Image], [FG_Image], [FG_Image], [FG_Image])
CREATE PARTITION FUNCTION [pf_Image](datetime) AS
RANGE RIGHT FOR VALUES (
N'2011-12-01T00:00:00.000'
, N'2013-04-01T00:00:00.000'
, N'2013-07-01T00:00:00.000'
);
Cela laisse essentiellement toutes les données dans la 4ème partition. Cependant, comme tout va dans le même groupe de fichiers. Les données sont actuellement réparties assez uniformément entre ces fichiers.
MISE À JOUR 2 Ce sont les attentes globales lorsque le processus ne fonctionne pas correctement.
Ce sont les attentes pendant la période pendant laquelle j'ai pu exécuter le processus qui fonctionne bien.
Le sous-système de stockage est un RAID connecté localement, aucun SAN n'est impliqué. Les journaux se trouvent sur un autre lecteur. Le contrôleur RAID est le PERC H800 avec une taille de cache de 1 Go. (Pour UAT) Prod est un PERC (810).
Nous utilisons une récupération simple sans sauvegarde. Il est restauré à partir d'une copie de production tous les soirs.
Nous avons également mis IsSorted property = TRUE
en SSIS puisque les données sont déjà triées.
PAGEIOLATCH_EX
et ASYNC_IO_COMPLETION
indiquent qu'il faut un certain temps pour obtenir des données du disque dans la mémoire. Cela peut être un indicateur d'un problème avec le sous-système de disque, ou il peut s'agir d'un conflit de mémoire. De combien de mémoire dispose SQL Server?
ASYNC_NETWORK_IO
signifie que SQL Server attendait d' envoyer des lignes à un client quelque part. Je suppose que cela montre l'activité de SSIS consommant des lignes de la table de transfert.