This is an EXPLAIN QUERY PLAN of one of the statements used to generate a 
report:

sele  order          from  deta
----  -------------  ----  ----
3     0              0     SCAN TABLE sgb_val_hist_ticket AS tx VIRTUAL TABLE 
INDEX 1: (~0 rows)
3     1              1     SCAN TABLE tag_141190 AS ta VIRTUAL TABLE INDEX 1: 
(~0 rows)
3     2              2     SCAN TABLE sgb_dd_prize_level AS pl VIRTUAL TABLE 
INDEX 1: (~0 rows)
3     0              0     USE TEMP B-TREE FOR GROUP BY
3     0              0     EXECUTE LIST SUBQUERY 4
3     0              0     EXECUTE LIST SUBQUERY 4
3     0              0     EXECUTE LIST SUBQUERY 4
3     0              0     EXECUTE LIST SUBQUERY 4
3     0              0     EXECUTE LIST SUBQUERY 4
3     0              0     EXECUTE LIST SUBQUERY 4
4     0              0     SCAN TABLE sgb_val_ticket AS tx VIRTUAL TABLE INDEX 
1: (~0 rows)
4     1              1     SCAN TABLE tag_141190 AS ta VIRTUAL TABLE INDEX 1: 
(~0 rows)
4     2              2     SCAN TABLE sgb_dd_prize_level AS pl VIRTUAL TABLE 
INDEX 1: (~0 rows)
4     0              0     USE TEMP B-TREE FOR GROUP BY
4     0              0     EXECUTE LIST SUBQUERY 5
4     0              0     EXECUTE LIST SUBQUERY 5
4     0              0     EXECUTE LIST SUBQUERY 5
4     0              0     EXECUTE LIST SUBQUERY 5
4     0              0     EXECUTE LIST SUBQUERY 5
4     0              0     EXECUTE LIST SUBQUERY 5
2     0              0     COMPOUND SUBQUERIES 3 AND 4 USING TEMP B-TREE (UNION)
1     0              0     SCAN SUBQUERY 2 (~200 rows)
1     0              0     USE TEMP B-TREE FOR GROUP BY
0     0              0     SCAN SUBQUERY 1 AS t1 (~100 rows)
0     1              1     SCAN TABLE sgb_dd_prize_level AS pl2 VIRTUAL TABLE 
INDEX 1: (~0 rows)
0     2              2     SCAN TABLE sgb_dd_draw AS dr VIRTUAL TABLE INDEX 1: 
(~0 rows)
0     0              0     USE TEMP B-TREE FOR ORDER BY

There are several CASE...END clauses and a UNION (of transaction data) cross 
joined to in-memory tables (of configuration data).

Note that the sgb_dd_prize_level table is referenced by INDEX 1 (which is nice 
to know) several times, but no indication of the fields used is given.

The following is clipped from the EXPLAIN of the same statement where select #3 
is implemented:

24    VColumn        7     27    45                   00  
sgb_val_hist_ticket.record
25    Integer        1     43    0                    00  NULL
26    Integer        1     44    0                    00  NULL
27    VFilter        8     52    43                   00  NULL
28    VColumn        8     5     50                   00  tag_141190.game_no
29    ...
30    VColumn        7     0     45                   00  
sgb_val_hist_ticket.jurisdiction_no
31    SCopy          50    46    0                    00  NULL
32    VColumn        8     8     47                   00  tag_141190.draw_no
33    VColumn        8     10    48                   00  
tag_141190.prize_share_no
34    Integer        1     43    0                    00  NULL
35    Integer        4     44    0                    00  NULL
36    VFilter        9     51    43    ^E              00  NULL
37    ...
38    ...
39    ...
40    ...
41    VColumn        9     0     56                   00  
sgb_dd_prize_level.jurisdiction_no

#24 tells us that table 7 is "sgb_val_hist_ticket"
#28 tells us that table 8 is "tag_141190"
#41 tells us that table 9 is "sgb_dd_prize_level"

"sgb_val_hist_ticket" is a large CTree based table
"tag_141190" is a "tag table" that splits binary data into a virtual table row.
"sgb_dd_prize_level" is an in-memory table

#27 is the VFilter call for table 8 with parameters passed beginning in 
register 43
#25 loads the INDEX NUMBER into register 43
#26 loads the argc of 1    into register 44
#24 loads the argv[0]      into register 45 (record BLOB)

So the tag table gets a binary field as the first and only user argument to the 
VFilter method.

#36 is the VFilter call for table 9 with parameters passed beginning in 
register 43
#34 loads the INDEX NUMBER into register 43
#35 loads the argc of 4    into register 44
#30 loads the argv[0]      into register 45 (jurisdiction_no)
#31 loads the argv[1]      into register 46 (game_no) copied from register 50
#32 loads the argv[2]      into register 47 (draw_no)
#33 loads the argv[3]      into register 48 (prize_share_no)

This compares favorably with the index definition of the table, so all is well.

Contrast this with the following excerpt from a "less performing" version of 
the same statement:

20    Integer        0     38    0                    00  NULL
21    Integer        0     39    0                    00  NULL
22    VFilter        7     57    38    ^E              00  NULL
23    VColumn        7     0     40                   00  
sgb_dd_prize_level.jurisdiction_no
24    Integer        1     38    0                    00  NULL
25    Integer        1     39    0                    00  NULL
26    VFilter        8     56    38    ^C              00  NULL
27    VColumn        8     27    46                   00  
sgb_val_hist_ticket.record
28    Integer        1     44    0                    00  NULL
29    Integer        1     45    0                    00  NULL
30    VFilter        9     55    44                   00  NULL
31    VColumn        9     5     51                   00  tag_141190.game_no
32    VColumn        7     1     52                   00  
sgb_dd_prize_level.game_no
33    Ne             52    54    51    collseq(BINARY)  6b  NULL
34    Ne             36    54    51    collseq(BINARY)  6b  NULL
35    VColumn        9     8     53                   00  tag_141190.draw_no
36    VColumn        7     2     54                   00  
sgb_dd_prize_level.draw_no
37    Ne             54    54    53    collseq(BINARY)  6b  NULL
38    VColumn        9     10    55                   00  
tag_141190.prize_share_no
39    VColumn        7     3     56                   00  
sgb_dd_prize_level.prize_share_no
40    Ne             56    54    55    collseq(BINARY)  6b  NULL

#22 is the VFilter call for sgb_dd_prize_level by INDEX 0 (physical order) with 
0 constraints = FULL TABLE SCAN

#26 is the VFilter call for sgb_val_hist_ticket by INDEX 1 with 1 constraint 
(jurisdiction_no, which happens to be constant) = FULL TABLE SCAN

#30 is the VFilter call for tag_141190 required to access the fields

#31..#40 perform the rest of the join on (jurisdiction_no, game_no, draw_no, 
prize_share_no)

There is no doubt that performing a full cross join will take significantly 
more time...


BTW: in the first excerpt, there are no checks of the returned fields against 
the constraints; this shows that the "omit" flags were set by the xBestIndex 
method (and the virtual table had better guarantee that only matching rows will 
be returned, or else...).

Hope this helps
Gunter

-----Ursprüngliche Nachricht-----
Von: Dominique Devienne [mailto:ddevie...@gmail.com]
Gesendet: Montag, 18. November 2013 09:44
An: General Discussion of SQLite Database
Betreff: Re: [sqlite] Using EXPLAIN to validate vtable xFilter [WAS: EXPLAIN 
QUERY PLAN]

On Mon, Nov 18, 2013 at 8:46 AM, Hick Gunter <h...@scigames.at> wrote:

> I use EXPLAIN to make sure that my virtual tables' xFilter methods get
> called with the proper parameters.
>

Hi Hick,

Would you mind sharing some details on this please? As a heavy vtable user, and 
those vtables implementing custom indexes (sometimes providing ordering too), 
I'm interested in what you mean exactly by this. We've had a few bugs in the 
past around vtable indexing, so if there's a technique to detect those you'd be 
willing to share, that'd be great.

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


--------------------------------------------------------------------------
 Gunter Hick
Software Engineer
Scientific Games International GmbH
Klitschgasse 2 – 4, A - 1130 Vienna, Austria
FN 157284 a, HG Wien
Tel: +43 1 80100 0
E-Mail: h...@scigames.at

This e-mail is confidential and may well also be legally privileged. If you 
have received it in error, you are on notice as to its status and accordingly 
please notify us immediately by reply e-mail and then delete this message from 
your system. Please do not copy it or use it for any purposes, or disclose its 
contents to any person as to do so could be a breach of confidence. Thank you 
for your cooperation.
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to