Thanks for your prompt response Dan. I missed mentioning that in my tests, I've 
made sure both queries lead to a single row (value) being returned in all cases.

-----Original Message-----
From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-boun...@sqlite.org] 
On Behalf Of Dan Kennedy
Sent: Thursday, April 15, 2010 11:59 AM
To: General Discussion of SQLite Database
Subject: Re: [sqlite] Index not used in simple look-up-value query


On Apr 15, 2010, at 10:51 PM, <diego.d...@bentley.com> wrote:

> In the light of the work on query-plan optimizations currently being  
> undertaken, I wonder if this issue could be looked at more closely.  
> I can confirm the returning type doesn't affect the performance I'm  
> seeing from the simple query. For example, returning an INT instead:
>
> SELECT ElementID FROM MyTable WHERE ElementID = @ElementID
>
> ... still runs slower (from 2 to 5 times slower) than the query  
> below (which doesn't make much sense).
>
> SELECT
>       MyDataTable.MyValue
> FROM
>       MyDataTable, MyIntermediateTable
> WHERE
>       MyIntermediateTable.ID1 = @ID1 AND
>       MyIntermediateTable.ID2 =  @ID2 AND
>       MyIntermediateTable.RecordID = MyDataTable.RecordID;

Maybe there are no rows in MyIntermediateTable that
match the WHERE conditions.

Dan.


> Thanks,
>
> Diego
>
> -----Original Message-----
> From: Diego Diaz
> Sent: Tuesday, April 13, 2010 4:24 PM
> To: General Discussion of SQLite Database
> Subject: RE: [sqlite] Index not used in simple look-up-value query
>
> Thanks Dan for clarifying that NotExists op does a seek on the IPK  
> column. However, I'm still confused as why the first query (simple)  
> takes much longer (from 2 to 5 times more) than the complicated one.  
> Some numbers:
>
> 50K runs of the simple query takes ~3 sec in total.
> 50K runs of the complicated query takes 0.5~1 sec in total.
>
> One would expect those timings to be the opposite (the complicated  
> one taking longer than the simpler one).
>
> One more detail: the simple query is returning a VARCHAR (Label) vs.  
> a FLOAT (MyValue) returned from the complicated one. Would the  
> returning type matter in the overall execution of these look-ups?
>
> Thanks!
>
> -----Original Message-----
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-boun...@sqlite.org 
> ] On Behalf Of Dan Kennedy
> Sent: Tuesday, April 13, 2010 2:11 PM
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] Index not used in simple look-up-value query
>
>
> On Apr 14, 2010, at 1:05 AM, <diego.d...@bentley.com> wrote:
>
>> Hello,
>>
>> I have a question regarding the query-optimizer. I've tested SQLite
>> with the following situation:
>>
>> 1 table defined as
>>
>> CREATE TABLE MyTable (ElementID INTEGER CONSTRAINT ElementID_PK
>> PRIMARY KEY AUTOINCREMENT, Label VARCHAR(255))
>>
>> After filling that table with lots of records (e.g. 100K), I tested
>> random look-ups of the "Label" column based on the ElementID column
>> (which is the primary-key of the table). That is, executing the
>> following query, which always returns 1 label-value, many times
>> (after preparing it only once), with random values for the
>> @ElementID parameter:
>>
>> SELECT Label FROM MyTable WHERE ElementID = @ElementID
>>
>> I've noticed that the performance of such query is not what I
>> expected. So, I looked at the query-plan (with the EXPLAIN keyword),
>> confirming that it is not using the primary-key, but it seems to be
>> doing table-scans instead (e.g. operation NotExists at addr 5):
>
> It is using the primary key. NotExists does a seek on
> the IPK column. This query should be fast.
>
>
>> addr    opcode  p1      p2      p3      p4      p5      comment
>> 0       Trace   0       0       0               0
>> 1       Variable        1       1       1       @ElementID      0
>> 2       Goto    0       10      0               0
>> 3       OpenRead        0       2       0       2       0
>> 4       MustBeInt       1       8       0               0
>> 5       NotExists       0       8       1               0
>> 6       Column  0       1       3               0
>> 7       ResultRow       3       1       0               0
>> 8       Close   0       0       0               0
>> 9       Halt    0       0       0               0
>> 10      Transaction     0       0       0               0
>> 11      VerifyCookie    0       2       0               0
>> 12      TableLock       0       2       0       MyTable 0
>> 13      Goto    0       3       0               0
>>
>> On the other hand, I've tried the same kind of "look-ups" but
>> involving a few joined-tables, leading to a more complex query like:
>>
>> SELECT MyDataTable .MyValue FROM MyDataTable, MyIntermediateTable
>> WHERE MyIntermediateTable.ID1 = @ID1 AND MyIntermediateTable.ID2 =
>> @ID2 AND MyIntermediateTable.RecordID = MyDataTable.RecordID;
>>
>> That query returns one value for a provided pair of integer IDs
>> (@ID1 and @ID2) and it involves an inner join between two tables
>> (MyDataTable.RecordID is a primary key autoincrement column).
>>
>> Executing that second query with random IDs many times in a row
>> leads to much better performance (takes less than half of the time)
>> than the simple query shown before (the size in number of rows of
>> all tables is comparable).
>>
>> After analyzing the query-plan for the second query, I can tell it
>> is using the indexes to seek into those tables as shown below (e.g.
>> operations at addr 13 through 16: SeekGe, IdxGE, IdxRowid and Seek).
>>
>> addr    opcode  p1      p2      p3      p4      p5      comment
>> 0       Trace   0       0       0               0
>> 1       Integer 1       1       0               0
>> 2       Variable        1       2       1       @ID1    0
>> 3       Variable        2       3       1       @ID2    0
>> 4       Goto    0       29      0               0
>> 5       OpenRead        1       7       0       3       0
>> 6       OpenRead        2       8       0
>> keyinfo(2,BINARY,BINARY)        0
>> 7       OpenRead        0       6       0       2       0
>> 8       SCopy   2       4       0               0
>> 9       IsNull  4       25      0               0
>> 10      SCopy   3       5       0               0
>> 11      IsNull  5       25      0               0
>> 12      Affinity        4       2       0       dd      0
>> 13      SeekGe  2       25      4       2       0
>> 14      IdxGE   2       25      4       2       1
>> 15      IdxRowid        2       6       0               0
>> 16      Seek    1       6       0               0
>> 17      Column  1       2       7               0
>> 18      MustBeInt       7       24      0               0
>> 19      NotExists       0       24      7               0
>> 20      Column  0       1       8       0       0
>> 21      RealAffinity    8       0       0               0
>> 22      ResultRow       8       1       0               0
>> 23      IfZero  1       25      -1              0
>> 24      Next    2       14      0               0
>> 25      Close   1       0       0               0
>> 26      Close   2       0       0               0
>> 27      Close   0       0       0               0
>> 28      Halt    0       0       0               0
>> 29      Transaction     0       0       0               0
>> 30      VerifyCookie    0       101     0               0
>> 31      TableLock       0       7       0
>> MyIntermediateTable     0
>> 32      TableLock       0       6       0       MyDataTable     0
>> 33      Goto    0       5       0               0
>>
>> Does anyone have any idea why the query-optimizer is not taking
>> advantage of the index associated with the primary key in the simple
>> query I showed initially? How can I rewrite such a query so it uses
>> the primary key index? I've tried "INDEXED BY" as well (after
>> creating a second index on the ElementID column) with no success.
>>
>> Thanks,
>>
>> Diego
>>
>> _______________________________________________
>> 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

_______________________________________________
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