Manzoor Ilahi Tamimy wrote:
I have tested my Code with the following PRAGMA and still not getting any change in time.
//--------------------------------------------------------------
sqlite3_exec(db, "PRAGMA temp_store=2", NULL, NULL, NULL);
sqlite3_exec(db, "PRAGMA synchronous=0", NULL, NULL, NULL);
sqlite3_exec(db, "PRAGMA count_changes=OFF", NULL, NULL, NULL);
sqlite3_exec(db, "pragma default_cache_size =65536", NULL, NULL, NULL);
sqlite3_exec(db, "pragma cache_size = 8192", NULL, NULL, NULL); //--------------------------------------------------------------

Actually I have a data in DBF files each file contain 10,30, 50 Million Records. What I am doing is First I have developed an Application to convert data from DBF to DB for using SQLite for fast data access.

The Requirment of the project is like this, because every time i will get data in DBF. so I will link my applcation with another application and will first convert it into DB and then I will run different Select Queries. What I want is Fast Insert And Fast Select. I have to display this hige data in Grid. I am Using MFC to develop this application.

Now I am thinking to Use SQLite in Memory Mode , may be it help me to reduce the Time.

I don't know much that How to use it memory mode. because the methode I am using is taking more time than DISK mode. here is a small Application in Which I was testing a DISK mode and Memory mode for INSERTION and SELECT. can you guide me how to use it properly in memory mode. I have tested this code on
P4, 3Ghz, 2 GB RAM , Windows XP Professional.
//******************************************************

#include "stdafx.h"

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "sqlite3.h"
int main(int argc, char *argv[])
{
    char *database = "backup.db";
//      char *database = ":memory:";
    sqlite3 *db;
    sqlite3_stmt *insert;
    int samples = 3000000;
    int i;
    time_t bgn, end;
    double t;
remove(database);
    bgn = time(NULL);
    sqlite3_open(database, &db);
        sqlite3_exec(db, "PRAGMA temp_store=2", NULL, NULL, NULL);
        sqlite3_exec(db, "PRAGMA synchronous=0", NULL, NULL, NULL);
        sqlite3_exec(db, "PRAGMA count_changes=OFF", NULL, NULL, NULL);
        sqlite3_exec(db, "pragma default_cache_size =65536", NULL, NULL,NULL);
sqlite3_exec(db, "pragma cache_size = 8192", NULL, NULL, NULL);

sqlite3_exec(db, "create table t (a integer, b float, c text,d integer, e float, f text, g float, h text)", NULL, NULL, NULL);


    sqlite3_exec(db, "begin transaction", NULL, NULL, NULL);

sqlite3_prepare(db, "insert into t values (?, ?, ?, ?, ?, ?, ? , ?)", -1, &insert, NULL);

    for (i = 0; i < samples; i++) {
sqlite3_bind_int(insert, 1, 44);
        sqlite3_bind_double(insert, 2,  444.4);
        sqlite3_bind_text(insert, 3, "two hundred", -1, SQLITE_STATIC);
        sqlite3_bind_int(insert, 4,  55);
        sqlite3_bind_double(insert, 5,  5.5);
        sqlite3_bind_text(insert, 6, "two hundred", -1, SQLITE_STATIC);
        sqlite3_bind_double(insert, 7,  66.6);
        sqlite3_bind_text(insert, 8, "two hundred", -1, SQLITE_STATIC);
        sqlite3_step(insert);
        sqlite3_reset(insert);
} // Insert Time check
//*********************************************************************
    end = time(NULL);
    sqlite3_exec(db, "commit transaction", NULL, NULL, NULL);
t = difftime(end, bgn); printf("Executed %d inserts in %.0f seconds, %.0f inserts/sec\n", samples, t, samples / t);
        getch();
//*********************************************************************

          // Select Time check
//*********************************************************************
    bgn = time(NULL);
    sqlite3_exec(db, "Select * from t", NULL, NULL, NULL);
    end = time(NULL);
    t = difftime(end, bgn);
    printf("Select in %.0f seconds", t);
    getch();
//*********************************************************************
sqlite3_close(db);

}

//******************************************************

DISK MODE
3000 000 INSERTS   31 Seconds   96774 INSERTS / Sec
"SELECT * from t"   5 Seconds.

MEMORY MODE
3000 000 INSERTS   53 Seconds   56604 INSERTS / Sec
"SELECT * from t"   5 Seconds.

Can I reduce the TIME of DISK mode or this is the limit.
WHY the Time in MEMORY mode is higher than DISK in case of INSERTION.

For the memory MODE I am just changing one statement is this the way to use memory mode. I changed char *database = "backup.db"; into char *database = ":memory:";

I really Need Help.

Thanks in Advance.

TAMIMY

---------------------------------------------------------------------------
I think that Derrell has already answered your question. What you are trying to do is inherently slow. You are doing a cross join of two large tables and counting the results. Depending upon which indexes you have defined (i.e. an index on IDC in either HVH or ITM tables), SQLite needs to scan one table from start to finish, and for each row in that table it uses an index to locate the matching rows in the other table.

You can look at the output of the "explain query plan" command to see how your tables and indexes are being scanned.

I suspect that this is a contrived tests case, and that it is not what you really need to get done. Can you explain what you are trying to do in more detail? For example, it looks like IDC is, or should be, the primary key for the ITM table, and that IDC is a foreign key in the HVH table. Is that true? How many records in the HVH table match each record in the ITM table; one, a few, or many? What information do you need to get from these tables (i.e. Is a count of the results what you are really after)?

If you can explain what you are trying to do in more detail, someone here can probably help you to generate a more suitable query.

HTH
Dennis Cote



Tamimy,

It's nice to see my test program making the rounds. ;-)

This is a modified version of the test code I posted to show that there was a small but definite SLOWDOWN when using :memory: databases compared to a database in a file on disk. It seems strange, but it is true. Use a disk file for best speed.

You have a couple of problems with your modifications that make your results a little misleading.

First, you are including the execution time of the pragmas and the create table statements in your timing of the inserts. The bgn=time() statement should be moved until it is just before the "begin transaction" is executed.

Second, you stop timing the inserts before you have done the commit. The commit is where the I/O operations are completed (i.e. buffers are flushed and the journal file is deleted). This time should be included, so you should move your end=time() statement after the "commit transaction" is executed.

Finally, you are not actually retrieving any data from the database during your select. You have not passed a callback function pointer to sqlite3_exec(), so it never returns any results to your application. If you are not going to read any results you might as well not perform the select, and the execution time will be zero.

I would recommend replacing the sqlite3_exec() call with a prepare/step/finalize loop in which you retrieve the result columns into local variables. The loop below should work (note, this code is untested and so may contain errors).


   sqlite3_stmt *select;
   int rc;
// vars to hold results.
   int a;
   double b;
   char *c = NULL;
   int c_sz = 0;
   int d;
   double e;
   char *f = NULL;
   int f_sz = 0;
   double g;
   char *h = NULL;
   int h_sz = 0;
bgn = time(NULL);
   sqlite3_prepare(db, "select * from t", -1, &select, NULL);
do {
       rc = sqlite3_step(select);
       if (rc == SQLITE_ROW) {
           // retrieve results
           a = sqlite3_column_int(select, 1);
           b = sqlite3_column_double(select, 2);
           read_string(select, 3, &c, &c_sz);
           d = sqlite3_column_int(select, 4);
           e = sqlite3_column_double(select, 5);
           read_string(select, 6, &f, &f_sz);
           g = sqlite3_column_double(select, 7);
           read_string(select, 8, &h, &h_sz);
       }
   } while (rc != SQLITE_DONE);
sqlite3_finalize(select);
   end = time(NULL);

   release_string(&c, &c_sz);
   release_string(&f, &f_sz);
   release_string(&h, &h_sz);

It uses the following functions to read the string values into dynamically allocated variable sized buffers, and to free those buffers.

   void read_string(sqlite3_stmt *qry, int col, char **str, int *len)
   {
       // ensure buffer is large enough to hold data
       int size = sqlite3_column_bytes(qry, col);
       if (size >= *len) {
           *str = realloc(*str, size + 1); // extra space for terminal nul
           if (!*str) {
fprintf(stderr, "Out of memory.\n"); exit();
           }
           *len = size + 1;
       }
// copy the data
       memcpy(*str, sqlite3_column_text(qry, col), size);
// add terminal nul
       (*str)[size] = 0;
   }

   void release_string(char **str, int *len)
   {
       free(*str);
       *str = NULL;
       *len = 0;
   }

One last thing. You said "I have to display this huge data in Grid". I don't think you really want to put 50 million records into a grid for display to a user. There is no way they can make use of that data. You may want to display small subsets of the data, but 50 million rows are simply too much for a human to deal with. You should probably review your design in this regard.

HTH
Dennis Cote

Reply via email to