Nous avons un certain nombre de bases de données qui stockent 10s à 100s de gigaoctets de données dans un des tableaux. Il contient des données d'image. Le problème est que beaucoup de ces bases de données ont été créées incorrectement. Fondamentalement, la clé primaire n'est pas réellement une clé primaire. Les ont été créés avec un index unique sur une colonne nullable. Et certains d'entre eux ont un int comme clé primaire au lieu d'un bigint.Manière efficace de modifier 100GB table
Nous avons donc lentement procédé à la correction de ces bases de données. Ils s'exécutent sur SQL Server 2000 via SQL Server 2008, bien que la plupart de ceux avec des problèmes de clé primaire soient sur SQL Server 2000. Le problème est, nous ne voulons pas verrouiller la base de données pendant une journée entière pendant qu'il convertit la table. Nous avons expérimenté plusieurs stratégies:
Dites à SQL Server de modifier directement le type de colonne. Cela verrouille la table jusqu'à ce qu'elle soit complète, et après l'avoir laissé la nuit dans de nombreux cas, elle n'était toujours pas terminée.
Insérez toutes les images dans une nouvelle table en une fois. Cela a été plus facilement interrompu, mais la table entière est essentiellement écrite dans le fichier journal dans le processus.
Insérez 100 lignes à la fois lorsque les lignes n'existent pas dans la table cible. L'avantage est qu'ils peuvent continuer à utiliser la base de données pendant que cela se passe (avec un gros succès) et qu'elle peut être arrêtée et redémarrée arbitrairement à tout moment, et cela empêche les fichiers journaux de plus de 100 Go. C'est ce que nous faisons actuellement, mais trouver les 100 premières lignes qui n'existent pas devient vraiment très lent lorsque la table cible devient de plus en plus grande. UPDATE STATISTICS et DBCC INDEXDEFRAG aident considérablement, mais dans la tentative la plus récente, nous sommes arrivés au point où même 100 images à la fois étaient là, ne répondant pas.
INSERT INTO %s SELECT TOP 100 Source.* FROM %s AS Source WITH (NOLOCK) LEFT OUTER JOIN %s AS Target WITH (NOLOCK) ON Source.DocumentID = Target.DocumentID WHERE Target.DocumentID IS NULL ORDER BY Source.DocumentID
La question est, est-il une option qui peut copier des données en vrac d'une manière efficace et peut être repris? Il n'est pas nécessaire d'être précis à 100%, nous pouvons toujours revenir en arrière et corriger les divergences à la fin, à condition de faire 99% du travail.
La clé primaire de cette table est non clusterisée. Convertir en un index clusterisé serait presque aussi douloureux que de recréer la table, car il doit réorganiser physiquement toutes les données. –
Le faire par plages est certainement plus efficace que la méthode de jointure. Je vais devoir voir comment ça se passe en pratique, mais j'espérais qu'il y avait un moyen d'exécuter les insertions d'une manière non atomique, où si ça s'arrêtait à mi-chemin, ça laisserait ce qui est déjà fait, et évitez l'écriture supplémentaire dans le fichier journal. –
@Bryce Wagner - Donc, si ce n'est pas en cluster sur le PK, alors faire une gamme équivalente ou un regroupement sur quoi * il * est * en cluster. (S'il vous plaît dites-moi qu'il a un cluster, et que ce n'est pas juste un HEAP) – BradC