Postgres vidage de seulement certaines parties des tables pour un instantané de développement

95

En production, notre base de données fait quelques centaines de gigaoctets. Pour le développement et les tests, nous devons créer des instantanés de cette base de données qui sont fonctionnellement équivalents, mais qui ne font que 10 ou 20 Go.

Le défi est que les données de nos entités commerciales sont dispersées dans de nombreux tableaux. Nous voulons créer une sorte d'instantané filtré afin que seuls certains des entités soient incluses dans le vidage. De cette façon, nous pouvons obtenir de nouveaux instantanés tous les mois environ pour le développement et les tests.

Par exemple, disons que nous avons des entités qui ont ces relations plusieurs-à-plusieurs:

  • L'entreprise compte N divisions
  • La division compte N employés
  • L'employé a N enregistrements de présence

Il y a peut-être 1 000 entreprises, 2 500 divisions, 175 000 employés et des dizaines de millions de fiches de présence. Nous voulons un moyen reproductible d'extraire, par exemple, les 100 premières entreprises et toutes ses divisions, employés et registres de présence. .

Nous utilisons actuellement pg_dump pour le schéma, puis exécutons pg_dump avec --disable-triggers et --data-only pour extraire toutes les données des petites tables. Nous ne voulons pas avoir à écrire des scripts personnalisés pour extraire une partie des données car nous avons un cycle de développement rapide et craignons que les scripts personnalisés soient fragiles et susceptibles d'être obsolètes.

Comment peut-on le faire? Existe-t-il des outils tiers qui peuvent aider à extraire des partitions logiques de la base de données? Comment s'appellent ces outils?

Tout conseil général également apprécié!

Jonathan Peterson
la source

Réponses:

108

Sur vos plus grandes tables, vous pouvez utiliser la commande COPY pour extraire des sous-ensembles ...

COPY (SELECT * FROM mytable WHERE ...) TO '/tmp/myfile.tsv'

COPY mytable FROM 'myfile.tsv'

https://www.postgresql.org/docs/current/static/sql-copy.html

Vous devez envisager de conserver un ensemble de données de développement plutôt que de simplement extraire un sous-ensemble de votre production. Dans le cas où vous écrivez des tests unitaires, vous pouvez utiliser les mêmes données que celles requises pour les tests, en essayant de toucher tous les cas d'utilisation possibles.

Ben
la source
1
J'ai utilisé cette technique avec beaucoup de succès pour faire la même chose que l'OP. Pour les essais, j'ai chargé COPY (SELECT ..) TO .. ​​les données contraintes dans une base de données "modèle" et utilisé CREATE DATABASE test_run_XX TEMPLATE product_snapshot_XX. J'ai bien sûr réduit les données au strict minimum pour que l'instantané du produit chargé et les opérations de création de db de test soient suffisamment rapides pour ne pas être un obstacle d'équipe.
Trey
5
Existe-t-il un moyen de faire en sorte que cela fonctionne si vous avez plusieurs tables jointes dont vous voulez des instantanés? COPY FROM ne prend pas en charge l'importation de plusieurs tables.
mlissner
1
Tu es l'homme ... Cela me facilite les choses, mais dans un autre but. Je l'ai utilisé pour déplacer des données du schéma public vers un schéma spécifique à l'utilisateur dans une application multi-locataire. Merci !
Jeremy F.
5
Notez que cette méthode ne met pas à jour les séquences sur les tables copiées, de sorte que d'autres insertions peuvent violer les contraintes de clé primaire.
user2859458
1
J'ai dû utiliser à la \copyplace de COPYaussi, car ce dernier était uniquement super-utilisateur. Heureusement, tout le reste a parfaitement fonctionné sans autres changements dans la version 9.1.
PJSCopeland
8

Je ne connais aucun logiciel qui le fasse déjà, mais je peux penser à 3 solutions alternatives. Malheureusement, ils nécessitent tous un codage personnalisé.

  1. Recréez toutes les tables dans un schéma séparé, puis copiez dans ces tables uniquement le sous-ensemble de données que vous souhaitez vider, utiliser INSERT INTO copy.tablename SELECT * FROM tablename WHERE ...et vider cela.

  2. Écrivez votre propre script pour vider les données sous forme d'instructions SQL. J'ai utilisé cette approche dans le passé et cela n'a pris que 20 à 30 lignes de PHP.

  3. Modifiez pg_dump pour qu'il accepte une condition avec l'option -t lors du vidage d'une seule table.

Aleksander Kmetec
la source
6

http://jailer.sourceforge.net/ le fait.

Paul Legato
la source
12
Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien pour référence. Les réponses aux liens uniquement peuvent devenir invalides si la page liée change.
talonmies
3
Cela n'a pas vraiment de sens ici. Le PO a demandé spécifiquement les noms des outils tiers qui font cela. L'essence de la réponse est donc uniquement: "Il existe un outil tiers appelé" Jailer "qui fait cela, à cette URL." Ce lien lui-même fournit toutes ces informations essentielles; il n'y a rien d'autre à ajouter. Si ce lien cesse de fonctionner, il peut facilement être déduit de l'URL que "le programme s'appelle Jailer", il serait donc redondant d'ajouter cela.
Paul Legato
2
Bien sûr, le lien est maintenant rompu et Google ne propose aucune alternative.
owensmartin
1
Le lien fonctionne actuellement pour moi, et googler pour "jailer postgres" est apparu apparu github.com/Wisser/Jailer .
Paul Legato
8
Peut-être que si vous avez ajouté une description utile de howvotre utilisation de cet outil, nous pourrions peut-être comprendre comment il atteint l'objectif
Bryan Ash