> OK...I added your trigger example as option 8.  And I had pasted the wrong
> version in my last email.  My timings were correct.  Your example also did
> sql_exec instead of using prepare so it will run slower.

Yes, but that should be marginal.

When I send my code the trigger version wasn't finished.
The intension is to compare a trigger update vs. manual
UPDATE statement within your loop.
I was also quite alarmed about the issue recently raised
here about the performace penality a trigger introduces.
So far my experiments based on your code doesn't confirm
this: Using a trigger is slightly faster vs. manual update
if everthing is within implicit transaction only - Makes sense.
The trigger is slightly slower when compared to manual UPDATE
when using commit bulks - Here the overhead of the trigger
appears slightly higher than a manual UPDATE, but: The difference
is maybe 10% and not 6 times slower as reported. Strange...

Anyway, I would like to add my trigger test in your version
but I can't compile due to missing 'gettimeofday' function.
Are you using MSVS ? Can you advice me where you have the
gettimeofday from ?

Sqlite does use fsync() to sync the file content prior
proceeding with journal/db file updating. Some month ago
I looked into that and found it is done 3 times per
"INSERT". I'm not speaking about sector write performance it is
related to the file syncs,
I don't see whats wrong with my arguments, please advice.

Thanks for the code by the way - I like the approach to create
a little test tool to have a common basis to experiment.

Marcus

> I also made this compilable on Unix too.
>
> On Unix my timing matches the run time and there are the right # of
> records in the database with the right values.  Unix is faster than
> Windows (8-core 2.6Ghz Unix system using SAS drives (I'm not sure of the
> model but I'm quite sure they are 7200RPM).
> Perhaps this is write caching on the disk?
>
> time ./batch 1600 1 0
> 1543.1
> real    0m1.042s
> user    0m0.046s
> sys     0m0.216s
>
> Something tells me your theory is wrong.  All 1600 records get inserted
> into the database in approx 1 second so it matches independent timing
> quite well.
>
> Here's my results with your trigger.  I'll maintain the timings are
> correct until somebody can prove this wrong.  Your theory is simply
> incomplete and is not taking into account SQLite's behavior.
>
> D:\SQLite>batch 504 1 0 -- simple single insert no batch
> 442.1
> D:\SQLite>batch 504 1 8 -- with trigger insert on 2nd table -- single row
> 307.3
> D:\SQLite>batch 504 1 9 -- trigger + in memory
> 5378.5
> D:\SQLite>batch 504 1 10 -- trigger +  index
> 212.3
> D:\SQLite>batch 504 1 12 -- trigger + WAL mode
> 2482.4
> D:\SQLite>batch 504 1 14 -- trigger + WAL mode + index
> 461.0
> D:\SQLite>batch 504 1 6 -- WAL mode + index
> 4608.0
> D:\SQLite>batch 504 504 6 -- WAL mode + index in one transaction
> 32256.0
> Of course you can't do your trigger (i.e. update) inside a transaction so
> there's some error checking for that now.
> You trigger is a factor of 10 slower.  I think we determined before that
> doing that update directly instead of a trigger would be faster.  I should
> add a method for that too.
>
> I also added a SYNCHRONOUS=OFF option#16
> That speeds it up a bit too.  I didn't see where FULL made much of a
> difference here so I just made OFF the option.
> D:\SQLite>batch 1600 1 0
> 414.6
> D:\SQLite>batch 1600 1 0
> 279.8
> D:\SQLite>batch 1600 1 16
> 602.4
> D:\SQLite>batch 1600 1 16
> 572.1
> D:\SQLite>batch 1600 1600 16
> 102400.0
>
> #include <stdio.h>
> #include <stdlib.h>
> #ifdef _WIN32
> #include <windows.h>
> #include <winbase.h>
> #else
> #include <sys/time.h>
> #endif
> #include <time.h>
> #include "sqlite3.h"
> double elapsed()
> {
>     double t1;
>     struct timeval tv;
>     static long base_seconds;
>     gettimeofday(&tv,NULL);
>     if (base_seconds==0) base_seconds=tv.tv_sec;
>     return (tv.tv_sec-base_seconds)+tv.tv_usec/(double)1000000;
> }
> int AddTrigger(sqlite3 *db)
> {
>         char SqlTxt[256];
>         int             rc;
>         strcpy(SqlTxt,"CREATE TRIGGER XX AFTER INSERT ON t FOR EACH ROW
> BEGIN ");
>         strcat(SqlTxt,"UPDATE t2 SET n = NEW.i+1;");
>         strcat(SqlTxt,"END;");
>  rc = sqlite3_exec(db,SqlTxt,NULL,NULL,NULL);
>         if (rc != SQLITE_OK) {
>                 puts(sqlite3_errmsg(db));
>         }
>         return(0);
> }
> int main(int argc, char *argv[])
> {
>  sqlite3 *db;
>  sqlite3_stmt *stmt=NULL;
>  int rc;
>  int n=0;
>  int nrec=0;
>  int interval=0;
>  int flags=0;
>  double t1;
>  if (argc != 4) {
>   fprintf(stderr,"Usage: %s nrecords commit_interval flags\n",argv[0]);
>   fprintf(stderr,"Flag 0 = simple table\n");
>   fprintf(stderr,"Flag 1 = in-memory database\n");
>   fprintf(stderr,"Flag 2 = add index\n");
>   fprintf(stderr,"Flag 4 = WAL mode\n");
>   fprintf(stderr,"Flag 8 = Add a trigger\n");
>   fprintf(stderr,"Flag 16 = Synchronous=Off\n");
>   fprintf(stderr,"Add flags to combine features\n");
>   exit(-1);
>  }
>  nrec=atoi(argv[1]);
>  interval=atoi(argv[2]);
>  flags=atoi(argv[3]);
>  if (flags & 1) {
>   rc=sqlite3_open(":memory:",&db);
>  }
>  else {
>   remove("batch.db");
>   rc=sqlite3_open("batch.db",&db);
>  }
>  if (rc != SQLITE_OK) {
>   puts(sqlite3_errmsg(db));
>  }
>  rc=sqlite3_exec(db,"create table t (i integer)",NULL,NULL,NULL);
>         if (rc != SQLITE_OK) {
>                 puts(sqlite3_errmsg(db));
>         }
>  rc=sqlite3_exec(db,"create table t2 (n integer)",NULL,NULL,NULL);
>         if (rc != SQLITE_OK) {
>                 puts(sqlite3_errmsg(db));
>         }
>  rc=sqlite3_exec(db,"insert into t2 values(0)",NULL,NULL,NULL);
>         if (rc != SQLITE_OK) {
>                 puts(sqlite3_errmsg(db));
>         }
>  if (flags & 16) {
>   rc=sqlite3_exec(db,"pragma synchronous=OFF",NULL,NULL,NULL);
>          if (rc != SQLITE_OK) {
>                  puts(sqlite3_errmsg(db));
>          }
>  }
>  if (flags & 2) {
>   rc=sqlite3_exec(db,"create index tx on t (i)",NULL,NULL,NULL);
>          if (rc != SQLITE_OK) {
>                  puts(sqlite3_errmsg(db));
>          }
>  }
>  if (flags & 4) {
>   rc=sqlite3_exec(db,"pragma journal_mode=WAL",NULL,NULL,NULL);
>          if (rc != SQLITE_OK) {
>                  puts(sqlite3_errmsg(db));
>          }
>  }
>  if (flags & 8) {
>   AddTrigger(db);
>   if (interval != 1) {
>    fprintf(stderr,"Can't do trigger and begin/commit together\n");
>    exit(-1);
>   }
>  }
>  sqlite3_prepare_v2(db,"insert into t values(?)",-1,&stmt,NULL);
>  t1=elapsed();
>  if (interval != 1) rc=sqlite3_exec(db,"begin",NULL,NULL,NULL);
>  while(n < nrec) {
>   ++n;
>   if (interval != 1 && (n% interval)==0) {
>    sqlite3_exec(db,"commit",NULL,NULL,NULL);
>    sqlite3_exec(db,"begin",NULL,NULL,NULL);
>   }
>   sqlite3_bind_int(stmt,1,n);
>   rc = sqlite3_step(stmt);
>   if (rc != SQLITE_DONE) {
>    puts(sqlite3_errmsg(db));
>   }
>   sqlite3_reset(stmt);
>  }
>  sqlite3_exec(db,"commit",NULL,NULL,NULL);
>  printf("%.1f\n",nrec/(elapsed()-t1));
>  sqlite3_close(db);
> }


_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to