web-dev-qa-db-fra.com

table mysqldump sans vider la clé primaire

J'ai une table répartie sur deux serveurs exécutant MySql 4. Je dois les fusionner en un seul serveur pour notre environnement de test.

Ces tables ont littéralement des millions d'enregistrements chacune, et la raison pour laquelle elles se trouvent sur deux serveurs est à cause de leur taille énorme. Toute modification et pagination des tables nous donnera un énorme coup de performance.

Parce qu'ils sont dans un environnement de production, il m'est impossible de les modifier de quelque façon que ce soit sur leurs serveurs existants.

Le problème est que la clé primaire est un champ d'incrémentation automatique unique, donc il y a des intersections.

J'ai essayé de comprendre comment utiliser la commande mysqldump pour ignorer certains champs, mais les touches --disable-modifient simplement la table, au lieu de se débarrasser complètement des clés.

À ce stade, il semble que je vais devoir modifier la structure de la base de données pour utiliser une somme de contrôle ou un hachage pour la clé primaire en tant que combinaison des deux champs uniques qui devraient en fait être uniques ... Je ne veux vraiment pas fais ça.

Aidez-moi!

40
Zee Spencer

si vous ne vous souciez pas de la valeur de la colonne auto_increment, chargez simplement le premier fichier, renommez la table, puis recréez la table et chargez le deuxième fichier. enfin, utilisez

INSERT newly_created_table_name (all, columns, except, the, auto_increment, column)
       SELECT all, columns, except, the, auto_increment, column
         FROM renamed_table_name
26
longneck

Pour résoudre ce problème, j'ai recherché cette question, trouvé la réponse de @ pumpkinthehead et réalisé que tout ce que nous devons faire est de trouver + remplacer la clé primaire de chaque ligne par NULL afin que mysql utilise à la place la valeur auto_increment par défaut.

(your complete mysqldump command) | sed -e "s/([0-9]*,/(NULL,/gi" > my_dump_with_no_primary_keys.sql

Sortie d'origine:

INSERT INTO `core_config_data` VALUES
    (2735,'default',0,'productupdates/configuration/sender_email_identity','general'),
    (2736,'default',0,'productupdates/configuration/unsubscribe','1'),

Sortie transformée:

INSERT INTO `core_config_data` VALUES
    (NULL,'default',0,'productupdates/configuration/sender_email_identity','general'),
    (NULL,'default',0,'productupdates/configuration/unsubscribe','1'),

Remarque: il s'agit toujours d'un hack; Par exemple, il échouera si votre colonne d'incrémentation automatique n'est pas la première colonne, mais résout mon problème 99% du temps.

22
Eric Seastrand

Vous pouvez créer une vue de la table sans la colonne de clé primaire, puis exécuter mysqldump sur cette vue.

Donc, si votre table "utilisateurs" a les colonnes: id, nom, email

> CREATE VIEW myView AS
  SELECT name, email FROM users

Edit: ah je vois, je ne sais pas s'il y a un autre moyen alors.

12
jimyi
  1. Clonez votre table
  2. Déposer la colonne dans la table de clonage
  3. Vider la table de clonage sans la structure (mais avec l'option -c pour obtenir des insertions complètes)
  4. Importez où vous voulez
6
Fedir RYKHTIK

C'est une douleur totale. Je contourne ce problème en exécutant quelque chose comme

sed -e "s/([0-9]*,/(/gi" export.sql > expor2.sql 

sur la décharge pour se débarrasser des clés primaires, puis

sed -e "s/VALUES/(col1,col2,...etc.) VALUES/gi" LinxImport2.sql > LinxImport3.sql

pour toutes les colonnes à l'exception de la clé primaire. Bien sûr, vous devrez faire attention à ce que ([0-9]*, ne remplace rien de ce que vous voulez réellement.

J'espère que cela aide quelqu'un.

6
pumpkinthehead
SELECT null as fake_pk, `col_2`, `col_3`, `col_4` INTO OUTFILE 'your_file'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM your_table;

LOAD DATA INFILE 'your_file' INTO TABLE your_table
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n';

Pour plus de fantaisie, vous pouvez définir un déclencheur avant l'insertion sur votre table de réception qui définit la nouvelle clé primaire pour la ligne de portée avant l'insertion, ce qui utilise des vidages réguliers et efface toujours votre paquet. Non testé, mais plutôt confiant.

4
Jeff Ferland

Utilisez une clé primaire temporaire factice:

Utilisez mysqldump normalement --opts -c. Par exemple, votre clé primaire est 'id'. Modifiez les fichiers de sortie et ajoutez une ligne "dummy_id" à la structure de votre table avec le même type que 'id' (mais pas la clé primaire bien sûr). Modifiez ensuite l'instruction INSERT et remplacez 'id' par 'dummy_id'. Une fois importé, déposez la colonne 'dummy_id'.

2
LinuxMatt

jimyi était sur la bonne voie.

C'est l'une des raisons pour lesquelles les clés à incrémentation automatique sont un PITA. Une solution consiste à ne pas supprimer les données mais à y ajouter.

CREATE VIEW myView AS
SELECT id*10+$x, name, email FROM users

(où $ x est un chiffre unique identifiant de manière unique la base de données d'origine) soit en créant la vue sur la base de données source (ce que vous suggérez peut-être pas possible) ou utilisez une routine d'extraction comme celle décrite par Autocracy ou chargez les données dans des tables intermédiaires sur le boîte de test.

Alternativement, ne créez pas la table sur le système de test - placez plutôt des tables séparées pour les données src puis créez une vue qui les récupère toutes les deux:

CREATE VIEW users AS
(SELECT * FROM users_on_a) UNION (SELECT * FROM users_on_b)

C.

0
symcbean

J'aime la route des tables temporaires.

create temporary table my_table_copy
select * from my_table;

alter table my_table_copy drop id;

// Use your favorite dumping method for the temporary table

Comme les autres, ce n'est pas une solution universelle (surtout compte tenu des millions de lignes de OP), mais même à 10 ^ 6 lignes, l'exécution prend plusieurs secondes mais fonctionne.

0
Aidan Miles

La solution que j'ai utilisée consiste à simplement effectuer une exportation SQL régulière des données que j'exporte, puis à supprimer la clé primaire des instructions d'insertion à l'aide d'un éditeur RegEx find & replace. Personnellement, j'utilise Sublime Text, mais je suis sûr que TextMate, Notepad ++ etc. peuvent faire de même.

Ensuite, je lance simplement la requête dans quelle base de données les données doivent être insérées en copiant coller la requête dans la fenêtre de requête de HeidiSQL ou PHPMyAdmin. S'il y a BEAUCOUP de données, j'enregistre la requête d'insertion dans un fichier SQL et j'utilise plutôt l'importation de fichiers. Le copier-coller avec d'énormes quantités de texte fait souvent geler Chrome.

Cela peut sembler beaucoup de travail, mais j'utilise rarement plus de quelques minutes entre l'exportation et l'importation. Probablement beaucoup moins que ce que j'utiliserais sur la solution acceptée. J'ai utilisé cette méthode de solution sur plusieurs centaines de milliers de lignes sans problème, mais je pense que cela deviendrait problématique lorsque vous atteignez les millions.

0
Hubro