web-dev-qa-db-fra.com

Transférer une table avec des millions de lignes de manière rapide sans blocage

Y a-t-il des solutions plus efficaces que simples INSERT INTO ou exporter et importer des fichiers pour déplacer des millions de lignes d'une table avec 3 colonnes à une table similaire dans une autre base de données, sans bloquer la base de données de destination et ne pas perdre l'un des enregistrements des transactions pouvant être réduites en cas de panne?

2
F.sb

Existe-t-il des solutions plus efficaces que de simples insert dans ou exportateur et d'importation de fichiers pour déplacer des millions de lignes d'une table avec 3 colonnes à une table similaire dans une autre base de données,

Votre meilleur choix pour cela va être SSIS.

sans bloquer la base de données de destination

Insertionner dans une table ne bloque la base de données , mais cela provoquera le blocage de la table à un degré ou un autre. La longueur et la gravité du blocage seront largement déterminées par le nombre d'index et de la manière dont ils conviennent à vos requêtes.

Si vous souhaitez réduire le blocage, insérez des données dans des morceaux plus petits. J'allais habituellement environ 1000 rangées à la fois pour éviter Serrure Escalation .

Une autre façon de réduire le blocage consiste à utiliser un niveau d'isolement optimiste sur des requêtes qui lisent les données de la mesure.

et ne pas perdre l'un des enregistrements dans les transactions pouvant être renvoyées en cas d'échec?

C'est une autre raison pour laquelle les lots plus petits sont une bonne idée. Il vous facilitera la tâche de déterminer la ligne incriminée, réessayez la transaction, etc.

Michael Swart: Modification des tables en ligne - Partie 1: Stratégie de migration

3
Erik Darling

Un flux de filet (Delta) est généralement recommandé pour les ensembles de données plus importants, mais cela dépendra de la fréquence à laquelle vous souhaitez l'exécuter et du volume Delta réel.

Si vous cherchez simplement à conserver une copie secondaire dans un état/synchronisation cohérent avec primaire, vous devriez peut-être examiner la réplication, le journal d'expédition ou des groupes de disponibilité.

Vous pouvez également utiliser BCP ou SSIS pour déplacer des données dans une nouvelle base de données dans une nouvelle table - qui ne verrouille pas la table de destination réelle - puis utilisez la commutation de partition, cela devrait entraîner un verrouillage minimum dans la base de données de destination.

Kendra Little a un très bon article sur la partition commutation: https://litttkendra.com/2017/01/19/why-YOU-Shald-Switch-In-Stager-tables-Instead-Of-Renaming/

1
Marcin Gminski

Dans mon travail, nous faisons un petit tour avec une application C # développée exclusivement pour déplacer environ 500-600 Go de données quotidiennement à partir de nos serveurs Oracle OLTP sur notre DataWarehouse SQL Server, avec un Beaucoup de filetage (environ 30 threads) ... La logique pourrait être transférée sans trop de problèmes aux SSIS (et c'est parce que nous avons testé d'abord la performance sur un package SSIS XD)

Nous ouvrons n Connexions à la table source et nous avons modifié la sélection pour filtrer les lignes en fonction du module (MOD dans Oracle,% dans SQL Server) d'un champ de numéro ... Cette astuce nous permet de lire une seule table avec un Beaucoup de threads en même temps (il s'agit de quelque chose de similaire qui se produit lorsque vous importez des données sur Hadoop à l'aide de SQOP, puisque SQOP utilise un champ de numéro indexé et divisez la tâche de lecture sur les travailleurs du N. gamme de données en même temps)

Par exemple, vous pouvez simplement créer 10 connexions à la même table et mettre ce type de requête pour lire les données avec une tâche de flux de données.

select number_field, varchar_field, date_field from table where (number_field % 10) = 0
select number_field, varchar_field, date_field from table where (number_field % 10) = 1
....
select number_field, varchar_field, date_field from table where (number_field % 10) = 8
select number_field, varchar_field, date_field from table where (number_field % 10) = 9

Chaque requête lirait une partie différente de données de la table source et insérerait sans problèmes sur la table de destination, si vous utilisez une destination OLDED, vous pouvez modifier les options pour décocher l'option pour verrouiller la table de destination et utiliser une taille de lot inférieure à 5000 des lignes, étant plus de 5000 lignes, les lignes sont enrichies d'abord sur la TEMP DB, puis transférée sur la table de destination, comme Erik dit, 1000 rangées n'est pas une mauvaise taille du lot

Avec cette astuce, nous déplacons des tables quotidiennes avec 10 rangées à environ 500 millions de lignes (données historiques ... qui sont mises à jour quotidiennement avec un processus fonctionnant sur le OLTP Oracle ... Nous tronquons la table de destination quotidiennement et lire toutes les lignes d'Oracle à nouveau ... C'est la raison pour laquelle notre processus atteigne l'heure de l'exécution)

1
figurettipy