1

J'ai fait un essai hier chez moi et je tombe sur des temps de traitement exagéremment longs. Pourtant je fais à peu près ce qui est dit dans les tutos. Voici mon code: int main(int argc, char **argv){      sqlite3 *db;      char *zErrMsg = 0;      int rc;      rc = sqlite3_open("toto.db", &db);      if( rc ){           fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));           sqlite3_close(db);           return 1;           //exit(1);      }      rc = sqlite3_exec(db, "CREATE TABLE tbl ( champ1 int,champ2 int) ", callback, 0, &zErrMsg);      if( rc!=SQLITE_OK ){           fprintf(stderr, "SQL error: %s\n", zErrMsg);           sqlite3_free(zErrMsg);      }      /* initialize random seed: */      //srand ( time(NULL) );      //char cmd[1000];            time_t start,end;      time (&start);      // Compile la requete      sqlite3_stmt* statement;      const char *zTail = 0;      for (int i =0;i<100;i++){           sqlite3_prepare(db,"INSERT INTO tbl (champ1,champ2) VALUES ( ?001, 5 )",1000,&statement,&zTail);           sqlite3_bind_int(statement, 1, i);           // Execute la           rc = sqlite3_step(statement);                 // Nettoyage           sqlite3_finalize(statement);           sqlite3_reset(statement);      }            rc = sqlite3_exec(db, "SELECT * FROM tbl", callback, 0, &zErrMsg);      if( rc!=SQLITE_OK ){           fprintf(stderr, "SQL error: %s\n", zErrMsg);           sqlite3_free(zErrMsg);      }      time (&end);      double dif = difftime (end,start);      printf ("It took you %.2lf seconds to do that.\n", dif );            scanf("%d");      time (&start);      for (int i =100;i<200;i++){           sqlite3_prepare(db,"INSERT INTO tbl (champ1,champ2) VALUES ( ?001, 5 )",1000,&statement,&zTail);           sqlite3_bind_int(statement, 1, i);           // Execute la           rc = sqlite3_step(statement);                 // Nettoyage           sqlite3_finalize(statement);           sqlite3_reset(statement);      }      rc = sqlite3_exec(db, "SELECT * FROM tbl", callback, 0, &zErrMsg);      if( rc!=SQLITE_OK ){           fprintf(stderr, "SQL error: %s\n", zErrMsg);           sqlite3_free(zErrMsg);      }      time (&end);      dif = difftime (end,start);      printf ("It took you %.2lf seconds to do that.\n", dif );      sqlite3_close(db);      return 0; }

ca m'affiche

It took you 12.00 seconds to do that.
...
It took you 11.00 seconds to do that.


:-/

Une idée?
Tout ce qui passe pas par le port 80, c'est de la triche.

2

Tout ce qui passe pas par le port 80, c'est de la triche.

3

pourquoi tu prépares la requête à chaque itération? je ferais plutot:

 sqlite3_prepare(db,"INSERT INTO tbl (champ1,champ2) VALUES ( ?001, 5 )",1000,&statement,&zTail);
for (int i =0;i<100;i++){        
          sqlite3_bind_int(statement, 1, i);
...


non? confus

edit: ah, ok , en fait une transaction, c'est pas con, vu que sinon sqlite écrit le disque a chaque insert.

4

Je suis obligé de la "préparer". Finalize et reset effacent le statement et le bytecode compilé de la requete (je sais pas lequel fait quoi exactement mais ils font ça). Et tu peux plus faire executer (tu peux plus faire "step") tant que tu as pas reset... En gros la préparation permet juste de pas utiliser exec pour mettre le i dans la requete.
Tout ce qui passe pas par le port 80, c'est de la triche.

5

et sprintf, ça fait pas pareil, là? trifus

6

le prepared statement c'est surtout plus rapide car l'engine n'a pas a recompile ta requete tout le temps.
(d'un point de vu securite aussi car tu ne vas pas avoir de sql injection avec les parametres ?)

7

oki, j'imagine, mais pourquoi il est obligé de recompiler sa requête dans la boucle, dans le code qu'il a posté en ./1 ?

8

sans prepared statement?

9

ben regarde son code:
 // Compile la requete
     sqlite3_stmt* statement;
     const char *zTail = 0;
     for (int i =0;i<100;i++){
          sqlite3_prepare(db,"INSERT INTO tbl (champ1,champ2) VALUES ( ?001, 5 )",1000,&statement,&zTail);
          sqlite3_bind_int(statement, 1, i);

          // Execute la
          rc = sqlite3_step(statement);
     
          // Nettoyage
          sqlite3_finalize(statement);
          sqlite3_reset(statement);
     }


pourquoi il compile la requête dans la boucle?

moi j'aurais fait:
 // Compile la requete
     sqlite3_stmt* statement;
     const char *zTail = 0;
     sqlite3_prepare(db,"INSERT INTO tbl (champ1,champ2) VALUES ( ?001, 5 )",1000,&statement,&zTail);
     for (int i =0;i<100;i++){
          sqlite3_bind_int(statement, 1, i);

          // Execute la
          rc = sqlite3_step(statement);
     
          // Nettoyage
          sqlite3_reset(statement);
     }
     sqlite3_finalize(statement);

(mais je sais pas comment marche sqlite en détails)

10

elle est compile la premiere fois ds la boucle. apres, c'est le moteur qui va aller la chercher (en tt cas, c'est le fonctionnement des db classiques, en gros, la requete SQL est la cle pour aller chercher la procedure pre-compilee)

11

12

Ouais squalyl, si je fais comme tu as écrit ça donne une violation d'accès. C'est vrai que du coup il recompile la requete je pense, on gagne "juste" à éviter le sprintf.

Là, j'ai un autre souci. Beaucoup plus grave (j'ai l'impression). Je suis dans un projet Visual Studio reglé en mode Unicode.

sqlite3_exec(db, "INSERT INTO toto (id,text) VALUES ( 24, 62 )", stubCallback, 0, &zErrMsg);


marche. Mais

sqlite3_stmt* statement;
		const char *zTail = 0;
		
		rc = sqlite3_prepare(db,"INSERT INTO toto (id,text) VALUES ( 24, 562 )",-1,&statement,&zTail);
		rc = sqlite3_step(statement);

		// Nettoyage
		sqlite3_finalize(statement);
		sqlite3_reset(statement);

plante royalement au niveau de sqlite3_reset ;-/
Je sais franchement pas quoi en faire.
Tout ce qui passe pas par le port 80, c'est de la triche.

13

Ok tout se rejoint, j'avais mal compris la doc:
The sqlite3_finalize() routine deallocates a prepared SQL statement. All prepared statements must be finalized before the database can be closed. The sqlite3_reset() routine resets a prepared SQL statement so that it can be executed again.


Donc, on peut faire:

	sqlite3_prepare(db,"INSERT INTO tbl (champ1,champ2) VALUES ( ?001, 5 )",-1,&statement,&zTail);	
	for (int i =0;i<10000;i++){
		sqlite3_bind_int(statement, 1, i);

		// Execute la
		rc = sqlite3_step(statement);

		// Nettoyage
		//sqlite3_finalize(statement);	// commenté == Ne libere pas le statement compilé
		sqlite3_reset(statement);
	}


et dans le cas plus haut, y a pas besoin de reset, pas de fuite de mémoire.
Tout ce qui passe pas par le port 80, c'est de la triche.

14

ah bah je comprends mieux smile
regarde le 2e (pre) du ./9 smile

ça va plus vite ou faut toujours la transaction pour que ça prenne pas 3 plombes?

15

ouais non la compilation factorisé n'a qu'un effet négligeable face à la transaction.
Tout ce qui passe pas par le port 80, c'est de la triche.

16

oki, ça m'étonne pas en fait, vu que c'est lié aux e/s, le temps de compil doit avoir un impact négligeable ^^