2009-06-25 7 views
3

J'ai des milliers de données analysées à partir d'énormes XML à insérer dans la table de base de données en utilisant PHP et MySQL. Mon problème est que cela prend trop de temps pour insérer toutes les données dans la table. Existe-t-il un moyen de scinder mes données en groupes plus petits afin que le processus d'insertion se fasse par groupe? Comment configurer un script qui traitera les données par 100 par exemple? Voici mon code:Insertion par lots de données dans la base de données MySQL en utilisant php

foreach($itemList as $key => $item){ 
    $download_records = new DownloadRecords(); 
    //check first if the content exists 
    if(!$download_records->selectRecordsFromCondition("WHERE Guid=".$guid."")){ 
     /* do an insert here */ 
    } else { 
     /*do an update */ 
    } 

}

* Note: $ itemList est d'environ 62000 et continue de croître.

Répondre

3

Utilisation d'une boucle for? Mais l'option la plus rapide pour charger des données dans MySQL est d'utiliser la commande LOAD DATA INFILE, vous pouvez créer le fichier à charger via PHP et le charger dans MySQL via un processus différent (ou comme une dernière étape dans le processus d'origine) .

Si vous ne pouvez pas utiliser un fichier, utilisez la syntaxe suivante:

insert into table(col1, col2) VALUES (val1,val2), (val3,val4), (val5, val6) 

afin que vous réduire au montant total des peines à exécuter.

EDIT: Vu votre extrait de code, il semble que vous puissiez bénéficier de la syntaxe INSERT ... ON DUPLICATE KEY UPDATE de MySQL, permettant à la base de données de faire le travail et de réduire le nombre de requêtes. Cela suppose que votre table possède une clé primaire ou un index unique.

défrayé la DB 100 lignes que vous pouvez faire quelque chose comme (S'IL VOUS PLAÎT LE LIRE ET FIXER À VOTRE ENVIRONNEMENT)

$insertOrUpdateStatement1 = "INSERT INTO table (col1, col2) VALUES "; 
$insertOrUpdateStatement2 = "ON DUPLICATE KEY UPDATE "; 
$counter = 0; 
$queries = array(); 

foreach($itemList as $key => $item){ 
    $val1 = escape($item->col1); //escape is a function that will make 
           //the input safe from SQL injection. 
           //Depends on how are you accessing the DB 

    $val2 = escape($item->col2); 

    $queries[] = $insertOrUpdateStatement1. 
    "('$val1','$val2')".$insertOrUpdateStatement2. 
    "col1 = '$val1', col2 = '$val2'"; 

    $counter++; 

    if ($counter % 100 == 0) { 
     executeQueries($queries); 
     $queries = array(); 
     $counter = 0; 
    } 
} 

Et executeQueries saisirait le tableau et envoyer une seule requête multiple:

function executeQueries($queries) { 
    $data = ""; 
    foreach ($queries as $query) { 
     $data.=$query.";\n"; 
    } 
    executeQuery($data); 
} 
+0

Oui, j'utilise une boucle for pour insérer les données dans la base de données distante. Le problème est que j'utilise une base de données distante pour que mon script s'exécute sur un serveur séparé pour alimenter l'autre base de données. – text

+0

Utilisez la plus petite quantité de phrases que vous pouvez gérer, c'est-à-dire, utilisez de grandes instructions d'insertion. –

+0

Oui, je peux utiliser un fichier et c'est ce que je prévois .. J'ai un souci sur cet insert, comment puis-je répéter un insert dans la table (col) VALUES (val) à répéter après 100 lignes sont atteintes? – text

0

Oui, faites ce que vous attendez de faire. Vous ne devriez pas essayer d'effectuer une insertion en masse à partir d'une application Web si vous pensez que vous pourriez rencontrer un délai d'attente, etc. Au lieu de déposer le fichier quelque part et avoir un démon ou cron etc., le ramasser et exécuter un travail par lots à partir de cron, assurez-vous qu'une seule instance s'exécute à la fois).

0

Vous devriez le mettre comme indiqué ci-dessus dans un répertoire temporaire avec un travail cron pour traiter les fichiers, afin d'éviter les délais d'attente (ou le fait que l'utilisateur perd son réseau).

Utilisez uniquement le Web pour les téléchargements.

Si vous voulez vraiment importer dans DB sur une requête Web, vous pouvez effectuer une insertion en bloc ou utiliser au moins une transaction qui devrait être plus rapide. Puis, pour limiter les insertions par lots de 100 (valider votre transaction si un compteur est compté% 100 == 0) et répéter jusqu'à ce que toutes vos lignes aient été insérées.

+0

comment implémenter $ count% 100 = 0? J'utilise un fichier pour vider les données dans ma table de destination. INSERT INTO table VALUES (val), (val) .... (val); et répétez INSERT après que les lignes atteignent 100 ou quelque chose? – text

+0

par exemple: CNX = mysql_connect() x = 0 alors (quelque chose à insérer) do: fetch_values_from_file (X, Y, Z) cnx.exec ("insérer dans les valeurs du tableau X, Y, Z", X , Y, Z) x + = 1 si x% 100: cnx.commit() – makapuf

Questions connexes