web-dev-qa-db-fra.com

Accélérer une grande création d'index en cluster?

J'ai une grande table, le nombre de lignes de la table est supérieur à 3 milliards, l'espace de données de cette table est d'environ 120 Go.

Et Intel Xeon CPU E5645 @ 2.4GHz (2 processeurs), 24 CPU, mémoire 64G, 64 bits Windows Server 2008 R2 Enterprise.

Je cours

create unique clustered index MyTable_IXC on tblFactFoo(barKey) on [PRIMARY]

Mais il a fallu plus de 6 heures (en fait, cela a signalé une erreur de clé dupliquée après 6 heures).

Lors de la fonctionner, la CPU était inférieure à 10% et le disque IO était inférieur à 20m/s, normalement d'environ 15 m/s, je me demande comment améliorer les performances de la création d'un index en cluster. un tel matériel puissant.

8
qwert

Vous devrez regarder le type d'attente lorsque la requête est en cours d'exécution. Les chances ont-vous besoin de disques plus rapides pour construire un indice sur une table qui va entraîner des quantités massives de lecture et d'écriture.

En résumé, vous devez lire la table 120 gigo, trier en fonction de la clé de clustering (qui va provoquer une tonne de renversement à TEMPDB écrit probablement 100 concerts à TEMPDB), puis écrivez l'index en cluster sur la base de données qui provoque 120 concerts d'écrivies.

En plus de cela, tous les index non clusters sur la table devront être reconstruits en même temps, de sorte que tous doivent être lus et réécrit également (ainsi que tout le déversement de la mémoire qui va avec la reconstruction des indices non clusters).

Vous pouvez accélérer les choses en désactivant les indices non clusterd, puis les construire manuellement après la reconstruction de l'index en cluster. Vous voudrez vous assurer que les utilisateurs finaux ne sont pas en mesure de toucher le système pendant que les index non clusters sont construits car leurs performances de requête seront affreuses jusqu'à ce que les index non clusters soient créés.

Assumant Enterprise Edition Vous pouvez créer les index couramment utilisés, puis informer les utilisateurs, puis créer les autres index en ligne afin que les utilisateurs travaillent.

Peu importe ce que vous regarderez une fenêtre de maintenance vraiment longue où vous claquerez les disques aussi difficiles que possible.

4
mrdenny

Voici quelques points à évaluer:

  1. Activez la compression de données: on dirait que vous êtes IO lié et que la CPU soit disponible. La compression des données pourrait être un bon compromis ici.
  2. Tourner SORT_IN_TEMPDB sur. Cela peut considérablement s'améliorer IO modèles (plus séquentiel IO et moins de fragmentation dans l'indice final).
  3. Construisez l'index dans un groupe de fichiers frais (présidé). Un groupe de fichiers frais n'est pas fragmenté, vous pouvez donc au moins vous débarrasser de ce problème. Utilisez l'initialisation du fichier instantané.

Ou charger les données correctement triées en premier lieu. Ensuite, vous n'avez pas besoin de construire un index du tout. Cela présente certains inconvénients mais vaut la peine d'être envisagé. La meilleure solution possible serait de se charger d'un index clustered partitionné à l'aide de l'indice ORDER pour le chargement en vrac. Un flux d'importation en vrac par partition et une partition par cpu ou par disque physique.

3
usr

Pour augmenter la vitesse de n'importe quelle commande SQL, vous devez disposer d'une base de données correctement configurée, j'espère donc que votre base de données est stockée sur un disque différent et que le maître et TEMPDB sont sur leur propre disque.

Qui étant dit qu'il y a plusieurs facteurs qui affectent la création de l'index: si la table est déjà triée et que, comme si cela ressemble à ce que vous construisez cela sur une table de tas, je dirais que cela n'est pas trié et que l'autre composant est le type de colonne sur lequel vous crée l'index sur. Les informations contenues dans un indice en clustere sont limitées par la quantité de colonnes ou la taille des octets des colonnes (selon la première éventualité) et, à mesure que certaines colonnes ne sont pas aussi bonnes candidates pour être des index en cluster.

Depuis que vous créez un index unique sur une table de tas, vous devez nettoyer les sapins afin de ne pas avoir de valeurs en double. Cela vous évitera de devoir construire à nouveau l'index.

Donc avant de gérer la requête de création d'index gérer cette première

SELECT 
   barKey
FROM
(
    SELECT 
        barKey, 
        COUNT(barKey) AS NoOfDuplicates 
    FROM 
        dbo.tblFactFoo WITH(NOLOCK)
    GROUP BY 
        barKey
)
WHERE
NoOfDuplicates > 1;

Après avoir exécuté cela et gérer les enregistrements dupliqués, vous pouvez exécuter ce qui suit, veuillez noter que cela utilisera un espace disque supplémentaire afin que vous aurez besoin au moins autant d'espace que la taille de cette table.

CREATE UNIQUE CLUSTERED INDEX IXC_MyTable ON dbo.tblFactFoo(barKey) WITH(SORT_IN_TEMPDB)
GO

Cela obligera le tri (qui est nécessaire lors de la création d'un index) pour se produire dans la base de données TEMPDB, puis l'avoir transféré et remplacer vos données.

Une alternative serait de créer une table en double avec le même nom, les clynes, etc., ajoutez la clé en cluster sur celle-ci, avant d'ajouter des enregistrements, puis d'exécuter cette commande:

MERGE INTO dbo.tblFactFoo AS source
USING dbo.tblFactFooIndexed AS destination ON source.barKey = destination.barKey
WHEN NOT MATCHED BY source THEN
INSERT INTO destination(col1, col2, barKey etc) VALUES (source.col1, source.col2, source.barKey etc)
WHEN MATCHED BY source AND (add extra conditions here if needed) THEN
-- INSERT / UPDATE or DELETE depending on how you want to handle duplicate keys

Comme il s'agit d'une opération définie que cela devrait, théoriquement, fonctionne beaucoup plus rapidement car le serveur SQL fonctionne sur des ensembles plus rapidement, puis il fonctionne sur des lignes. Une fois que vous avez terminé, déposez la première table et renommez la deuxième table.

Si vous avez besoin d'une aide supplémentaire avec la commande MERGE ici, voici le lien avec MSDN: http://msdn.microsoft.com/en-us/library/bb510625.aspx

0
Toni Kostelac