2011-04-14 5 views
1

Je suis nouveau à tcl. Je me suis connecté à une base de données SqLite.tcl insertion de la base de données et de récupération lente

J'ai environ 100 000 enregistrements que je veux insérer dans la base de données après le calcul. J'utilise la commande suivante pour insérer des enregistrements dans la base de données 100,000times. Je suis sûr que je fais quelque chose de mal ici. Quelle serait la bonne façon de faire cela?

Pour l'insertion:

db eval {insert into table values(value1,value2,value3,value4)} 

Pour la récupération, je dois faire l'opération de sélection au moins 1000 fois, les choses sont terriblement lentes:

db eval {select x as x, y as y from table} { 
    set z [expr $z + $x + $y] 
} 
+0

Mettez-vous le 'db eval {select ...} {...}' dans une boucle, ou s'agit-il simplement de mille lignes dans le résultat? –

Répondre

0

Je ne peux pas parler à la partie sqlite du question parce que je n'ai pas utilisé sqlite dans quelques années, mais une cause de dégradation des performances est votre déclaration expr. Vous devez bloquer les arguments expr, ce qui devrait accélérer la partie de la boucle considérablement:

set z [expr {$z + $x + $y}] 
0

Oui, des insertions simples de Tcl dans une table sql n'est pas le moyen le plus rapide pour accomplir ce que vous voulez.

Pour accélérer les choses, vous devez écrire la table que vous voulez dans un fichier externe et slurp les données dans avec une seule instruction db.

Vous souhaitez écrire les données comme ceci:

set fh [open temp_file w] 
set rowid 0 
# loop 
    puts $fh [join [list $value1 $value2 $value3 $value4] \t] 
# end loop 
close $fh 

Puis, en utilisant la méthode copy, vous pouvez lire tout en un seul coup:

db copy replace values temp_file 

Et comme pour le calcul d'une somme, Je ne sais pas pourquoi vous n'utilisez pas SQL lui-même pour faire la sommation. Il existe de nombreux exemples sur le Web de la façon de le faire. Ici areacouple. J'imagine votre déclaration sql serait quelque chose comme:

db select sum(x+y) from table 

ou peut-être

db select sum(x+y) as z from table 
+0

Je dois utiliser certaines valeurs que je calcule dans le programme avec les valeurs que je reçois de la table aussi. –

2

Par défaut, chaque insertion est une seule transaction. C'est très lent. Vous pouvez regrouper vos insertions en une seule transaction de, disons, 100 insertions, et accélérer considérablement les choses.

db eval { BEGIN TRANSACTION } 

... do some insertions ... 

db eval { END TRANSACTION } 

ou

db transaction { 

... do some insertions ... 

} 

Hors de la boîte, SQLite est extrêmement sûr, mais assez lent. Si vous savez ce que vous faites, et que vous êtes prêt à risquer la corruption db sur un crash de disque, alors il y a plusieurs optimisations que vous pouvez faire qui fournissent des améliorations de vitesse spectaculaires.

En particulier:

  • synchronisation Désactiver (PRAGMA synchrone = OFF;)
  • Group écrit dans les transactions
  • tables Index
  • base de données Utilisation dans la mémoire

Si vous N'ayant pas exploré tout cela, vous courez probablement beaucoup plus lentement que vous ne le pourriez.

+0

Cela fonctionne bien pour les insertions. Y a-t-il un moyen d'accélérer les sélections? –

+0

En général, les sélections sont rapides, ce qui signifie qu'il y a moins de possibilités de les optimiser. Avez-vous regardé la réponse que j'ai liée? La prochaine chose à essayer serait de désactiver la synchronisation. Mais je soupçonne que cela n'améliorera pas les sélections. – ravenspoint

+0

J'ai regardé l'exemple de déclaration que vous avez posté. Etes-vous sûr que le goulot d'étranglement est en sqlite? Combien de temps TCL prend-il pour exécuter 1000 fois z [expr $ z + $ x + $ y]? – ravenspoint

Questions connexes