Complètement la copie d'un postgres table avec SQL
AVERTISSEMENT: Cette question est similaire à la dépassement de pile question ici, mais aucune de ces réponses pour mon problème, comme je l'expliquerai plus tard.
Je suis en train de copier un tableau de grande taille (~40M lignes, 100+ colonnes) dans postgres, où beaucoup de colonnes sont indexées. Actuellement, je utiliser ce bits de SQL:
CREATE TABLE <tablename>_copy (LIKE <tablename> INCLUDING ALL);
INSERT INTO <tablename>_copy SELECT * FROM <tablename>;
Cette méthode a deux questions:
- Il ajoute que les indices avant que les données de l'ingestion, de sorte qu'il sera beaucoup plus long que la création de la table sans indices et ensuite l'indexation après la copie de toutes les données.
- Ce n'est pas copier `SERIAL' des colonnes de style correctement. Au lieu de créer un nouveau "compteur" sur le nouveau tableau, il définit la valeur par défaut de la colonne dans la nouvelle table au comptoir du passé table, sens de ne pas incrémenter comme des lignes sont ajoutées.
La taille de la table fait de l'indexation d'un problème en temps réel. Il rend également impossible de la vider sur un fichier puis de le ré-acquisition. Je n'ai pas aussi l'avantage d'une ligne de commande. J'ai besoin de le faire en SQL.
Ce que je voudrais faire est de droite créer une copie exacte avec certains miracle de commande, ou si ce n'est pas possible, pour copier le tableau avec toutes les contraintes, mais sans indices, et assurez-vous qu'ils sont les contraintes 'dans l'esprit' (aka un nouveau compteur pour une SÉRIE de colonnes). Puis, copie toutes les données avec un SELECT *
puis copiez tous les indices.
Sources
-
Un Débordement de pile question à propos de la copie de la base de données: Ce n'est pas ce que je suis demander ce, pour trois raisons
- Il utilise l'option de ligne de commande
pg_dump -t x2 | sed 's/x2/x3/g' | psql
et dans ce cadre je n'ai pas accès à la ligne de commande - Il crée les indices de pré données de l'acquisition, qui est trop lent
- Il n'a pas de mise à jour de la série des colonnes correctement, comme l'attestent les
default nextval('x1_id_seq'::regclass)
- Il utilise l'option de ligne de commande
-
Méthode pour réinitialiser la valeur de la séquence pour une postgres table: C'est très bien, mais malheureusement, il est très manuel.
- Votre question est probablement une copie de stackoverflow.com/questions/198141/...
- J'ai vu cette question, il n'y avait pas de réponses satisfaisantes qui peut réellement faire ce que je demande, mais cela me demande de faire un autre edit de mon post.
- Il n'y a pas une meilleure réponse.
- Il y a trois problèmes majeurs avec le plus voté solution sur cette page. L'un, ils utilisent la ligne de commande fonctions dans
pg_dump -t x2 | sed 's/x2/x3/g' | psql
que je n'ai pas accès trop. De deux, Il crée les indices avant d'ajouter les données qui seront très lent! Trois, le numéro de SÉRIE par défaut du paramètre références à la première tabledefault nextval('x1_id_seq'::regclass).
Ces trois défauts je l'ai déjà indiqué dans ma question. Vous me dites il n'y a pas de solution à l'un de ces? @peter - Ce n'est qu'une Question de Programmation.
Vous devez vous connecter pour publier un commentaire.
Bien, tu vas avoir à faire certaines de ces choses à la main, malheureusement. Mais il peut être fait à partir de quelque chose comme psql. La première commande est assez simple:
Cela va créer nouvelletable avec oldtable de données, mais pas d'index. Puis vous avez à créer les index et les séquences, etc sur votre propre. Vous pouvez obtenir une liste de tous les index sur une table avec la commande:
Puis exécutez psql -E pour accéder à votre base de données et utiliser \d l'ancienne table. Vous pouvez ensuite mangle ces deux requêtes pour obtenir les informations sur les séquences:
Remplacer que 74359 ci-dessus avec l'oid vous obtenez à partir de la requête précédente.
La
create table as
fonctionnalité dans PostgreSQL peut-être maintenant la réponse que l'OP a été à la recherche pour.https://www.postgresql.org/docs/9.5/static/sql-createtableas.html
Cela va créer une identique tableau avec les données.
Ajoutant
with no data
copie le schéma sans les données.Cela va créer le tableau avec toutes les données, mais sans les index et les déclencheurs etc.
create table my_table_copy (like my_table including all)
Create table syntaxe qui comprendra tous les déclencheurs, index, contraintes, etc. Mais ne pas inclure des données.
(like my_table including all)
peut ne pas satisfaire les OP qui ne veulent pas d'index, mais c'est parfait pour moi d'essayer d'obtenir un tableau avec toutes les contraintes.Le plus proche "miracle de commande" est quelque chose comme
En particulier, il s'occupe de la création de l'index après le chargement de la table de données.
Mais qui ne réinitialise pas les séquences; vous devez le script que vous-même.
Pour copier une table complètement, y compris à la fois la structure des tables et des données, vous utilisez l'instruction suivante:
Pour copier un tableau de la structure de l'absence de données, vous ajoutez le SANS clause de DONNÉES à l'instruction CREATE TABLE comme suit:
Pour copier un tableau avec des données partielles à partir d'une table existante, vous utilisez l'instruction suivante:
AVERTISSEMENT:
Toutes les réponses qui utilisent pg_dump et toute forme d'expression régulière pour remplacer le nom de la table source sont vraiment dangereux. Que faire si vos données contient la sous-chaîne que vous êtes en train de remplacer? Vous finirez par la modification de vos données!
Je propose un deux passe-solution:
Voici un exemple écrit en Ruby:
Dans le ci-dessus, je suis en train de copier les "membres" de la table en "members_copy_20130320". Mes données spécifiques regexp est /^\d+\. t.*(?:t|f)$/
Ci-dessus le type de solution qui fonctionne pour moi. Caveat emptor...
edit:
OK, voici une autre façon de pseudo-syntaxe shell pour la regexp aversion des gens:
psql -f mytable_copy_schema.sql mydb
pg_dump -a-t mytable mydb > mytable_data.sql
Apparemment, vous voulez à "reconstruire" une table. Si vous ne souhaitez reconstruire une table, de ne pas copier, alors vous devriez utiliser les armes à la place.
Vous aurez à choisir l'index, essayez de choisir celui qui convient à vos requêtes. Vous pouvez toujours utiliser la clé primaire si aucun autre indice est adapté.
Si votre tableau est trop grand pour être mis en cache, le CLUSTER peut être lent si.
create table newTableName (comme oldTableName y compris index);
insérez dans newTableName sélectionnez * à partir de oldTableName
Cela a fonctionné pour moi 9.3