SQL Server - Exporter une grande table sans clé primaire

9

J'ai besoin de synchroniser une grande table ~ 500 millions de lignes sans clé primaire entre SQL Server et MySQL. La table n'a qu'un index composite non unique en cluster.

J'ai une connexion ODBC entre les serveurs, mais une importation de ~ 8 millions de lignes a pris environ 45 minutes, donc je pense qu'une importation unique plus importante serait déraisonnable car des interruptions peuvent survenir à tout moment. Je ne peux pas changer la structure de table existante, je peux ajouter d'autres tables. Après une lecture supplémentaire, offset / fetch n'est pas une option pour les grandes tables. "Sélectionnez ... où x entre ... et ..." n'est pas une option car je n'ai pas de clé unique.

Comment exporter la table en lots garantis pour contenir toutes les lignes? Mon problème est que, puisque la clé en cluster n'est pas unique, la commande après cela ne garantirait pas que les lignes physiques ont le même ordre entre les requêtes consécutives et la commande après toutes les colonnes prendrait trop de temps. Et comment recommanderiez-vous de migrer les lots, via des fichiers ODBC ou CSV?

personne
la source
Ce sera répétition (opération usuelle) ou opération ponctuelle?
Bogdan Bogdanov
L'exportation initiale sera une opération unique, les changements de synchronisation comme les nouveaux enregistrements ou les mises à jour doivent être répétitifs. CDC n'est pas une option, mais étudiera plus en détail après la migration initiale.
personne le
Je pense que pour recevoir de l'aide à ce sujet, vous devez expliquer plus en détail l'ensemble du processus (il semble que vous ayez un problème très complexe)
Bogdan Bogdanov
Vous notez que «puisque la clé en cluster n'est pas unique, le tri après cela ne garantirait pas que les lignes physiques ont le même ordre entre les requêtes consécutives». Étant donné que l'ordre des lignes n'est pas conservé (sauf si vous avez des données de séquence), vous ne pouvez pas compter sur l'obtention du même ordre physique des lignes. L'ordre des lignes ne correspond pas par défaut à l'ordre d'insertion ni à l'ordre d'index, mais est défini par la clause ORDER BY .
RLF
Oui, RLF, je suis d'accord. Les colonnes sont toutes des entiers, A, B, C, D, E. La clé groupée est sur ABC. Une combinaison ABC n'est pas unique, ni une combinaison ABCD. «Ordonner par» une ou des colonnes non uniques me permettrait-il d'exporter la table entière par lots? Et Bogdan Bodganov, la plateforme Stack décourage les problèmes complexes, il vaut mieux juste répondre à la question. Comment exporter la grande table complète le plus rapidement possible par lots sans perte de lignes?
personne le

Réponses:

0

En supposant que vous n'avez pas de mises à jour ou de suppressions sur la table source, vous pouvez essayer ce qui suit:
1. Faites une copie de la table existante en utilisant la syntaxe CTAS (pour SQLServer c'est SELECT * into source_table_copy FROM source_table). Une telle opération est très rapide même pour des tables énormes.
2. Ajoutez un after insertdéclencheur sur source_tablelequel copie le ou les nouveaux enregistrements source_table_copy.
3. Maintenant, lorsque tous les nouveaux enregistrements source_tablesont source_table_copyégalement affichés, vous pouvez déplacer les données de la table copiée vers Mysql par lots. Par exemple, si vous avez un lien entre 2 serveurs, tout peut être fait dans le corps de la procédure stockée TSQL.
Par exemple, un morceau de code qui déplace jusqu'à 20 enregistrements vers un nouveau serveur pourrait ressembler

 --declare table variable to keep deleted records until they delivered to target host 
  BEGIN TRANSACTION;
  DELETE TOP (20) FROM source_table_copy OUTPUT DELETED.* INTO @Table_Var;

  --insert data into linked server , or to csv file
  COMMIT; 

Il est également possible d'utiliser CURSOR pour lire les données puis les supprimer avec la where current ofclause.

** Idéalement, vous devez empêcher les applications d'insérer des données au source_tablecours de l'étape 1. Si c'est absolument impossible, j'irai avec un after insertdéclencheur qui est ajouté juste avant l'étape 1 et supprimé juste après qu'il soit fait qui copie les données dans une autre table que je peux fusionner plus tard avec source_table_copy.

a1ex07
la source
Merci pour la solution, j'essayais aussi quelque chose, cependant avec un insert normal. Je vais essayer la syntaxe CTAS pour voir si cela accélère les choses. Question de suivi, si cela ne vous dérange pas: le "déclencheur après insertion" affecterait-il les performances?
personne le
Étant donné que le corps du déclencheur est très simple (il suffit d'insérer des données dans une autre table), l'impact sur les performances sera minime.
a1ex07 du