J'importe une grande quantité de données dans une base de données vide et avant de commencer, j'ai désactivé tous les index non cluster non uniques pour voir si je pouvais améliorer les performances de l'importation.
Maintenant, je veux réactiver les index, et je me demande si je peux faire quelque chose pour l'optimiser.
Il y a> 100 tables et près de 2 000 index à reconstruire. La base de données a une taille de 200 Go.
La section clé du script que j'exécute est la suivante:
declare c_toggle_index cursor FORWARD_ONLY READ_ONLY for
select 'alter index ' + QUOTENAME(i.name) + ' on ' + o.name + ' rebuild'
from sys.indexes as i
Inner Join sys.objects o
On o.object_id = i.object_id
Where o.is_ms_shipped = 0
And i.index_id >= 1
and i.type > 1
and i.is_disabled = 1
J'ai envisagé de définir ONLINE = OFF pour l'instruction alter index, mais comme les index commencent désactivés, je n'étais pas sûr que ce paramètre aurait un effet. J'ai également envisagé de définir SORT_IN_TEMPDB = ON, mais comme les fichiers tempdb sont sur le même lecteur que les fichiers .mdf des bases de données, j'ai supposé qu'il n'y avait également aucun avantage à le faire.
Lors de l'exécution du script de reconstruction, j'ai remarqué que j'avais beaucoup de types d'attente CXPACKET. Je ne comprends pas vraiment pourquoi ce serait ou si c'est un problème que je devrais chercher à résoudre.
Un dernier point qui peut être pertinent: l'ensemble de mon serveur est actuellement inactif à part cette importation de données dans la base de données. Il n'y a aucune autre activité utilisateur à considérer ou à s'inquiéter; ma seule préoccupation est d'importer les données dans la base de données dans les plus brefs délais.
CXPACKET
attentes: les reconstructions d'index elles-mêmes analysent les index (même l'index en cours de reconstruction ), et ces analyses peuvent utiliser le parallélisme. Vous ne devriez pas vous inquiéter de ces attentes - le parallélisme est probablement utile.Réponses:
Atteindre des performances d'importation optimales dans ce scénario nécessite trois choses:
Journalisation minimale
La réalisation d'insertions à journalisation minimale dans une table en cluster vide sans index non cluster nécessite:
SIMPLE
ouBULK_LOGGED
des modèles de récupération de base de donnéesTABLOCK
etORDER
astuces)Note latérale:
Création d'index non cluster séparément
Les avantages de cette opération sont les suivants:
CREATE INDEX
est enregistré de façon minimale si le modèle de récupération n'est pasFULL
Éviter les lectures physiques
Idéalement, les données à importer seront stockées sur une machine distincte, ou au moins sur un stockage physique distinct de celui utilisé pour héberger la base de données.
Le serveur de base de données doit avoir suffisamment de mémoire pour contenir la plus grande table de base dans le cache, avec suffisamment de mémoire pour les opérations de tri nécessaires lors de la création d'index non cluster.
Un bon modèle consiste à charger rapidement la table de base (charge d'index clusterisée à journalisation minimale), puis à créer tous les index non cluster pour cette table pendant que ses pages de données sont toujours mises en cache.
La question décrit un processus par lequel les tables de base sont chargées en premier, puis les index non cluster sont construits. La définition du curseur n'utilise pas de
ORDER BY
clause pour regrouper au moins les générations d'index non cluster sur la même table.Le résultat probable est que les pages de données de différentes tables sont lues à plusieurs reprises dans le cache, puis supprimées car les index non clusterisés sont créés dans un ordre non déterministe.
Le coût des lectures physiques répétées domine complètement les avantages d'une journalisation minimale obtenue en créant des index non-cluster séparément. Cela explique pourquoi vous avez constaté que le chargement des tables avec des index existants est plus rapide (car tous les index non cluster pour une table donnée sont conservés avant de passer à la table suivante).
Sommaire
Le processus d'importation doit être retravaillé pour charger en bloc une table à la fois. Cela signifie charger la table et construire tous les index non cluster avant de passer au suivant. L'instance SQL Server doit avoir suffisamment de mémoire disponible pour contenir la plus grande table et effectuer le plus grand tri d'index non cluster en même temps.
Vous pouvez également essayer d'activer TF 610 avant de charger les données dans des tables avec des index non cluster déjà en place. Ce n'est généralement pas aussi rapide que la méthode précédente, mais cela peut être assez rapide.
Consultez les informations suivantes pour plus d'informations:
Le guide des performances de chargement des données
Opérations pouvant être enregistrées de façon minimale
la source