2008-10-23 19 views
4

Quel est le moyen le plus rapide de charger des données à partir de fichiers plats dans une base de données MySQL, puis de créer les relations entre les tables via des clés étrangères?Chargement de fichiers plats dans une base de données MySQL normalisée

Par exemple ... Je dispose d'un fichier plat dans le format suivant:

[INDIVIDUAL] [POP] [MARKER] [GENOTYPE] 

"INDIVIDUAL1", "CEU", "rs55555","AA" 
"INDIVIDUAL1", "CEU", "rs535454","GA" 
"INDIVIDUAL1", "CEU", "rs555566","AT" 
"INDIVIDUAL1", "CEU", "rs12345","TT" 
... 
"INDIVIDUAL2", "JPT", "rs55555","AT" 

que je dois charger dans quatre tableaux:

IND (id,fk_pop,name) 
POP (id,population) 
MARKER (id,rsid) 
GENOTYPE (id,fk_ind,fk_rsid,call) 

Plus précisément, comment peut-on alimenter les clés étrangères d'une manière qui échelles? Les chiffres sont de l'ordre de 1000+ individus, chacun avec 1 million + génotypes.

+0

Merci pour le conseil jusqu'à présent ... bien qu'actuellement je dois gérer les clés étrangères par programme avant de charger – pufferfish

Répondre

4

Il existe un moyen plus simple. Tout d'abord, assurez-vous que vous avez une contrainte UNIQUE sur les colonnes qui devraient en avoir une (nom, population, rsid).

Ensuite, utilisez quelque chose comme ce qui suit:

LOAD DATA INFILE 'data.txt' IGNORE INTO TABLE POP FIELDS TERMINATED BY ',' 
    ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES 
    (@name, population, @rsid, @call); 
LOAD DATA INFILE 'data.txt' IGNORE INTO TABLE MARKER FIELDS TERMINATED BY ',' 
    ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES 
    (@name, @population, rsid, @call); 
LOAD DATA INFILE 'data.txt' IGNORE INTO TABLE IND FIELDS TERMINATED BY ',' 
    ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES 
    (name, @population, @rsid, @call) 
    SET fk_pop = (SELECT id FROM POP WHERE population = @population); 
LOAD DATA INFILE 'data.txt' IGNORE INTO TABLE GENOTYPE FIELDS TERMINATED BY ',' 
    ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES 
    (@name, @population, @rsid, call) 
    SET fk_ind = (SELECT id FROM IND where name = @name), 
    fk_rsid = (SELECT id FROM MARKER where rsid = @rsid); 

Notez où le @ est utilisé pour indiquer les variables, plutôt que les noms de colonnes. Dans les 2 premières données de chargement, celles-ci sont simplement utilisées pour ignorer les données. Dans le deuxième 2, ils sont utilisés pour rechercher les clés étrangères.

Peut ne pas être très rapide, d'accord :).

9

Je prendrais une approche en plusieurs étapes pour ce faire.

  1. Chargez les données dans une table temporaire, qui est correspondant au format de fichier que vous avez
  2. Écrire des requêtes à faire les autres insertions, à partir des tableaux généraux, puis faire joint pour obtenir les valeurs FK.
0

Vous pouvez commencer avec les tables de base sans clé étrangère. Vous recherchez ensuite les ID lorsque vous insérez des données dans les autres tables.

Une autre idée est que vous pouvez remplacer les ID dans le fichier plat (INDIVIDUAL1, CEU, ... etc.) Par GUID. puis les utiliser directement en tant qu'ID et clés étrangères (j'ai remarqué que cette performance est étiquetée, cela peut ne pas donner la meilleure "performance").