2010-02-09 5 views
1

J'essaie d'insérer plus de 70 000 lignes dans une base de données javascript (en utilisant Chrome 5.0.317.2). Les inserts prennent beaucoup de temps. La page actuelle se charge en quelques secondes, et je peux voir le progrès que le pourcentage augmente très lentement à mesure que chaque ligne est insérée. Il a fallu environ une heure pour terminer l'insertion de tous les enregistrements. Existe-t-il un moyen d'optimiser les insertions, ou d'une manière ou d'une autre de démarrer avec une base de données SQLite préchargée?Base de données JavaScript Insert de masse

<script src="jquery.1.3.2.min.js" type="text/javascript" charset="utf-8"></script> 
<script type="text/javascript" charset="utf-8"> 
// Truncated to 1 row for example. There are really 76547 rows. 
var zipcodes = var zipcodes = [{"city_name":"AMHERST","city_alias":"AMHERST","zipcode":"01002"}]; 
var db; 
function openMyDatabase() { 
    var shortName = 'mydb'; 
    var version = '1.0'; 
    var displayName = 'mydb'; 
    var maxSize = 65536; 
    db = openDatabase(shortName, version, displayName, maxSize); 
    db.transaction(
     function(transaction) { 
      transaction.executeSql(
       'CREATE TABLE IF NOT EXISTS zipcode ' + 
       ' (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' + 
       ' city_name TEXT NOT NULL, ' + 
       ' city_alias TEXT NOT NULL, ' + 
       ' zipcode TEXT NOT NULL)' 
      ); 
     } 
    ); 
    $.each(zipcodes, function(i, zipcode) { 
     insertZipcode(zipcode.city_name, zipcode.city_alias, zipcode.zipcode, i); 
    }); 
} 

function errorHandler(transaction, error) { 
    alert('Oops. Error was '+error.message+' (Code '+error.code+')'); 
    return true; 
} 

function insertZipcode(cityName, cityAlias, zipcode, i) { 
    db.transaction(
     function(transaction) { 
      transaction.executeSql(
       'INSERT INTO zipcode (city_name, city_alias, zipcode) VALUES (?, ?, ?);', 
       [cityName, cityAlias, zipcode], 
       function(){ 
        $('#counter').html((100 * i/zipcodes.length) + '%'); 
       }, 
       errorHandler 
      ); 
     } 
    ); 
    return false; 
} 

$(function() { 
    openMyDatabase(); 
}); 
</script> 

Solution: Du côté de PHP, j'ai fait un tableau associatif et utilisé le code comme clé et un éventail de villes comme la valeur, et je l'ai couru à travers json_encode et passé que le javascript. Du côté javascript j'ai pu obtenir très rapidement une liste des villes pour un code postal particulier en utilisant le code suivant:

var zipcodes = {"55437":["MINNEAPOLIS","BLOOMINGTON"]}; //truncated 
alert('Cities in 55437: ' + zipcodes['55437'].join(', ')); 

Répondre

1

Pourquoi ne pas utiliser un XML préchargé? De cette façon, vous réduirez le temps de chargement, et le temps de recherche pourrait être réduit par un certain type d'indexation, peut-être une indexation de hashtable ou une recherche binaire. Ceci réduirait la flexibilité, ce qui signifie que vous devrez changer le XML et le compiler à l'aide d'un outil - que je ne sais pas si quelque chose comme ça existe; mais permettra de meilleures performances, surtout si vous travaillez dans un appareil limité comme un iPhone.

+0

J'ai essayé d'utiliser XML/XPath, mais qui était encore trop lent, mais en utilisant JSON, j'ai pu faire un objet géant qui est facile et rapide à rechercher codes ZIP. –

+0

Intéressant de savoir que JSON est plus rapide que XML. Totalement compréhensible. – jpabluz

3

Un problème que je vois est que vous essayez d'insérer une ligne à temps, cela peut causer beaucoup de frais généraux en faisant des connexions etc ...

Ce serait plus rapide si vous pouviez insérer plusieurs rangs (peut-être 20 ou 50 en un coup) en une seule fois. Pourquoi ne pas utiliser un XML préchargé au lieu de créer tous les champs lors du chargement de la page Web? Vous pouvez insérer plusieurs lignes en utilisant une procédure effeciente ou INSERT INTO ou quelque chose.

0

Une heure est probablement trop longue dans tous les cas, mais même si vous réduisez cela de beaucoup, vous avez encore une attente importante. Il va probablement payer pour générer un nouveau thread pour gérer ce processus séparément de votre thread d'interface utilisateur pour préserver la réactivité pour l'utilisateur.

3

Si vous ne pouvez pas le déplacer vers quelque chose côté serveur (Javascript n'est vraiment pas un outil pour un travail comme ça), définitivement, regrouper plusieurs insertions ensemble comme le suggère Suraj. 90% du travail est de commencer la connexion, commencer la transaction, terminer la transaction, fermer la connexion. 10% sont des opérations de DB réelles.

transaction.executeSql(' 
      INSERT INTO zipcode (city_name, city_alias, zipcode) VALUES (?, ?, ?); 
      INSERT INTO zipcode (city_name, city_alias, zipcode) VALUES (?, ?, ?); 
      INSERT INTO zipcode (city_name, city_alias, zipcode) VALUES (?, ?, ?); 
      ... //20-50 lines like this, maybe generated by a loop. 
      ',[ 
      cityName1, cityAlias1, zipcode1, 
      cityName2, cityAlias2, zipcode2, 
      cityName2, cityAlias3, zipcode3, 
      ... // a matching table, generated by a loop as well. 
      ], 
      ... 
1

Ce que je l'ai fait pour résoudre ce problème est d'abord créer une chaîne contenant un transanction avec tous ses exécute, puis l'exécuter en utilisant javascript méthode eval

jsonResponse = Ext.util.JSON.decode(result.responseText); 
     jsonIndex = 0; 
     var consulta = "DB.transaction(function (transaction){"; 
     while(jsonResponse[jsonIndex] != null){ 
      var ins = jsonResponse[jsonIndex].instruccion; 
      ins = ins.replace(/&quot;/gi, "\""); 
      consulta+= "transaction.executeSql('"+ins+"'); ";     
      jsonIndex++; 
     } 
     consulta+="});"; 
     eval(consulta); 
Questions connexes