Hi,

*******************************************************************************************************************
A) What version of SQLite are you using ?
- We are using SQLite version 3.6.17
- We are using SQLite through the C++ SOCI library - 3.1.0

*******************************************************************************************************************
C) How many rows are there in that table ?
In my first email I posted simplified version of the problem. In order to avoid 
a possible misleading it is probably better to post results from the real 
version. IMO, the problem is the same, but I could be wrong. So here is the 
real database table:

CREATE TABLE "event" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"type" INTEGER NOT NULL,
"current" INTEGER NOT NULL DEFAULT 1,
"timestamp" INTEGER NOT NULL,
"file_id" INTEGER,
"folder_id" INTEGER,
"deleted" INTEGER NOT NULL,
"previous_name" TEXT,
"previous_folder_id" INTEGER,
"rsub_id" INTEGER,
"person_id" INTEGER,
"guest_id" INTEGER
, transparent INTEGER NOT NULL DEFAULT 0, major integer not null default 0);

CREATE INDEX IDX_event_1 ON event (deleted, major, id);

CREATE TRIGGER update_event
AFTER UPDATE ON event
FOR EACH ROW
WHEN (old.type != new.type)
BEGIN
        update event set major = new.type in (3, 4, 5, 6, 7, 8, 9) where id = 
new.id;
END;

CREATE TRIGGER insert_event
AFTER INSERT ON event
BEGIN
        update event set major = new.type in (3, 4, 5, 6, 7, 8, 9) where id = 
new.id;
END;

CREATE INDEX IDX_event_2 on event (file_id, deleted, id);

=========================================================

select max(id) from event;  - 366899
select count(id) from event where deleted = 0 and major = 0; - 326564
select count(id) from event where deleted = 0 and major = 1; - 34899

*******************************************************************************************************************
B) What is the result of EXPLAIN SELECT ?
I'm posting the results of EXPLAIN QUERY PLAN and EXPLAIN from the real table 
in order to avoid misleading.

=============================================================
explain query plan select e.type, e.id, e.rsub_id, e.person_id, e.timestamp, 
e.file_id, e.previous_name, e.previous_folder_id, e.transparent, e.folder_id 
from event e where e.deleted = 0 and major = 0 and e.id > 330557 order by e.id 
asc limit 1;

selectid       order   from    detail
0       0       0       SEARCH TABLE event AS e USING INDEX IDX_event_1 
(deleted=? AND major=?)

=============================================================
explain select e.type, e.id, e.rsub_id, e.person_id, e.timestamp, e.file_id, 
e.previous_name, e.previous_folder_id, e.transparent, e.folder_id from event e 
where e.deleted = 0 and major = 0 and e.id > 330557 order by e.id asc limit 1

addr   opcode  p1      p2      p3      p4      p5      comment
0       Trace   0       0       0       ""      00      
1       Noop    0       0       0       ""      00      
2       Integer 1       1       0       ""      00      
3       Goto    0       29      0       ""      00      
4       OpenRead        0       2       0       14      00      
5       OpenRead        2       9       0       k(4,B,B,B,B)    00      
6       Integer 0       2       0       ""      00      
7       Integer 0       3       0       ""      00      
8       SeekGe  2       26      2       2       00      
9       IdxGE   2       26      2       2       01      
10      IdxRowid        2       4       0       ""      00      
11      Seek    0       4       0       ""      00      
12      Le      6       25      4       ""      6c      
13      Column  0       1       7       ""      00      
14      IdxRowid        2       8       0       ""      00      
15      Column  0       9       9       ""      00      
16      Column  0       10      10      ""      00      
17      Column  0       3       11      ""      00      
18      Column  0       4       12      ""      00      
19      Column  0       7       13      ""      00      
20      Column  0       8       14      ""      00      
21      Column  0       12      15      0       00      
22      Column  0       5       16      ""      00      
23      ResultRow       7       10      0       ""      00      
24      IfZero  1       26      -1      ""      00      
25      Next    2       9       0       ""      00      
26      Close   0       0       0       ""      00      
27      Close   2       0       0       ""      00      
28      Halt    0       0       0       ""      00      
29      Transaction     0       0       0       ""      00      
30      VerifyCookie    0       26      0       ""      00      
31      TableLock       0       2       0       event   00      
32      Integer 330557  6       0       ""      00      
33      Goto    0       4       0       ""      00      

*******************************************************************************************************************
D) Are you testing this inside your own application or using the SQLite shell 
tool ?

Here is the pseudo/real code of my testing scenario.

agent_root_revision.minor_rev = 330556;
agent_root_revision.major_rev = 330557;

auto beg = boost::chrono::high_resolution_clock::now();

enum { count_iterations = 1000 };
for (int i = 0; i < count_iterations; ++i)
{
        int j = 300 * i; // i'm using this in order to avoid returning results 
from the disk cache

        // pseudo code the query is the same as above with parameters id and 
major , deleted is hardcoded to where deleted = 0
       SELECT 1 EVENT DATA WHERE ID > (agent_root_revision.major_rev-j) and 
major = 1;

        // pseudo code the query is the same as above with parameters id and 
major , deleted is hardcoded to where deleted = 0
       SELECT 1 EVENT DATA WHERE ID > (agent_root_revision.minor_rev-j) and 
major = 0;
}          

auto end = boost::chrono::high_resolution_clock::now();

auto dur = boost::chrono::duration_cast<boost::chrono::milliseconds>(end - beg);

LOG(log_, lg_normal) << "AGENT REV: " << agent_root_revision << ". TIME FOR " 
<< count_iterations << " ITERATIONS: " << dur;

==========================================================================================
and the results are (I did more than 10 measurements) with the original table 
and with the modified table (with dup_id)
The results are in the same range for the two cases.

original table result - 2014-Mar-26 09:53:38.247243:NORM: AGENT REV: 
330557:330556. TIME FOR 1000 ITERATIONS: 38828 milliseconds

modified table result - 2014-Mar-26 10:02:57.000232:NORM: AGENT REV: 
330557:330556. TIME FOR 1000 ITERATIONS: 252 milliseconds

Note that in the second case only the query is modified to use the dup_id:
select e.type, e.id, e.rsub_id, e.person_id, e.timestamp, e.file_id, 
e.previous_name, e.previous_folder_id, e.transparent, e.folder_id from event e 
where e.deleted = 0 and major = 0 and e.dup_id > 330557 order by e.dup_id asc 
limit 1;
*******************************************************************************************************************
Some additional information.
If I run ANALYZE on this db. The EXPLAIN QUERY PLAN returns different that a 
different index will be used (just by id)
selectid       order   from    detail
0       0       0       SEARCH TABLE event AS e USING INTEGER PRIMARY KEY 
(rowid>?)

*******************************************************************************************************************
Let me know if you need some more information that I can provide.

I'm about to test the proposed - "id" INTEGER PRIMARY KEY. I'll post what are 
the results with it.

I'll ask our guys if it is ok to upload the db on your server.

Thank you for the help,
Pavel.
________________________________________
From: sqlite-users-boun...@sqlite.org <sqlite-users-boun...@sqlite.org> on 
behalf of Graham Holden <sql...@aldurslair.com>
Sent: Wednesday, March 26, 2014 8:57 AM
To: General Discussion of SQLite Database
Subject: Re: [sqlite] Primary key used in compound index

The assertion that AUTOINCREMENT has no effect (here and in another post) is 
incorrect.  Without it, SQLite MAY reuse a key from deleted rows; with it, this 
will not happen.

Sent from Samsung Galaxy Note

-------- Original message --------
From: Simon Slavin <slav...@bigfraud.org>
Date: 26/03/2014  12:50  (GMT+00:00)
To: General Discussion of SQLite Database <sqlite-users@sqlite.org>
Subject: Re: [sqlite] Primary key used in compound index


On 25 Mar 2014, at 8:19pm, Pavel Vazharov <pa...@anchorworks.com> wrote:

> "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,

Can you try this as exactly the following:

"id" INTEGER PRIMARY KEY,

leaving everything else out.  I assure you that it will obey the 'NOT NULL' and 
'AUTOINCREMENT' anyway.  The reason is that SQLite has explicit understanding 
of exactly that phrase for primary keys.

> "type" INTEGER NOT NULL,
> "some_integer_data" INTEGER NOT NULL,
> "some_string_data" TEXT,
> "deleted" INTEGER NOT NULL,
> major INTEGER NOT NULL DEFAULT 0
> );
> CREATE INDEX IDX_test_event_1 ON test_event (deleted, major, id);
>
> When I execute:
>
>
> explain query plan select * from test_event where deleted = 0 and major = 1 
> and id > 5 order by id asc limit 1;
>
> It returns:
>
>
> ?selectid order from detail
> 0 0 0 SEARCH TABLE test_event USING INDEX IDX_test_event_1 (deleted=? AND 
> major=?)
>
> So I can see that the id is not used, only delete and major part of the 
> compound index are used. In our scenario this leads to slow selects, really 
> slow.

Not sure whether the id column should be mentioned but the index you created is 
an excellent index for that SELECT, so you should be getting extremely fast 
results.  Can you try using EXPLAIN instead of EXPLAIN QUERY PLAN ?  It will 
tell you more about how the query is being handled.

> And the select statement runs about 100 times faster than the previous one.

I agree.  Makes no sense.

> My question is: Is there a way the primary key to be used as a part of the 
> compound index?

You should think of SQLite sneakily adding the primary key onto the end of 
every index you declare, whether you ask for it or not.  When devising 
searching and sorting methods, SQLite knows it's there and should be using it 
correctly.

> Adding additional column works, but it will increase the database size and 
> will slow down the insert statements because this additional column needs to 
> be updated with trigger or with additional query.

I agree this is annoying and we should be able to solve your strange problem.

Can you post the following information:

A) What version of SQLite are you using ?
B) What is the result of EXPLAIN SELECT ?
C) How many rows are there in that table ?
D) Are you testing this inside your own application or using the SQLite shell 
tool ?

If you want to make it really easy for us to test this, could you put up some 
test data on a server somewhere ?  But we may not need it so don't work too 
hard on it at this stage.

Note to others: I get the same results from XQP using SQLite 3.7.13 and no data 
in the table.

Simon.
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to