Paul wrote:
> I've traced this issue down to the simplest test case:
>
> CREATE TABLE IF NOT EXISTS foo
> (
> id INTEGER,
> baz INTEGER,
> PRIMARY KEY(id)
> );
>
> CREATE INDEX IF NOT EXISTS baz_foo_idx ON foo(baz, id);
>
> CREATE TABLE IF NOT EXISTS bar
> (
> foo INTEGER,
> PRIMARY KEY(foo),
> FOREIGN KEY(foo) REFERENCES foo(id) ON DELETE CASCADE
> );
>
> WITH RECURSIVE
> cnt(x, y) AS (VALUES(1, 1) UNION ALL SELECT x + 1, x + 1 FROM cnt WHERE x <
> 200000)
> INSERT INTO foo(id, baz) SELECT x, y FROM cnt;
>
> WITH RECURSIVE
> cnt(x) AS (VALUES(1) UNION ALL SELECT x + 3 FROM cnt WHERE x < 50000)
> INSERT INTO bar SELECT x FROM cnt;
>
> This query takes too much time:
>
> SELECT id FROM foo WHERE baz = 10000 AND id IN (SELECT foo FROM bar) LIMIT 1;
EXPLAIN SELECT id FROM foo WHERE baz = 10000 AND id IN (SELECT foo FROM bar)
LIMIT 1;
addr opcode p1 p2 p3 p4 p5 comment
---- ------------- ---- ---- ---- ------------- -- -------------
0 Init 0 24 0 00 Start at 24
1 Integer 1 1 0 00 r[1]=1; LIMIT counter
2 OpenRead 2 3 0 k(3,,,) 02 root=3 iDb=0;
baz_foo_idx
3 Integer 10000 2 0 00 r[2]=10000
4 Once 0 6 0 00
5 OpenRead 3 4 0 1 00 root=4 iDb=0; bar
6 Rewind 3 22 0 00
7 Rowid 3 3 0 00 r[3]=rowid
8 IsNull 3 21 0 00 if r[3]==NULL goto
21
9 Once 1 11 0 00
10 OpenRead 4 4 0 1 00 root=4 iDb=0; bar
11 Rewind 4 21 0 00
12 Rowid 4 4 0 00 r[4]=rowid
13 IsNull 4 20 0 00 if r[4]==NULL
goto 20
14 SeekGE 2 20 2 3 00 key=r[2..4]
15 IdxGT 2 20 2 3 00 key=r[2..4]
16 IdxRowid 2 5 0 00 r[5]=rowid
17 ResultRow 5 1 0 00 output=r[5]
18 DecrJumpZero 1 22 0 00 if (--r[1])==0
goto 22
19 Next 2 15 0 00
20 NextIfOpen 4 12 0 00
21 NextIfOpen 3 7 0 00
22 Close 2 0 0 00
23 Halt 0 0 0 00
24 Transaction 0 0 3 0 01 usesStmtJournal=0
25 TableLock 0 2 0 foo 00 iDb=0 root=2 write=0
26 TableLock 0 4 0 bar 00 iDb=0 root=4 write=0
27 Goto 0 1 0 00
If I've understood this correctly, it's the equivalent of this pseudocode:
cursor c3 = scan bar
for each row in c3:
cursor c4 = scan bar
for each row in c4:
cursor c2 = search (10000, c3.rowid, c4.rowid) in baz_foo_idx
for each row in c2:
output c2.rowid
stop
This looks like a bug.
As a workaround, drop "id" from the index (the rowid is always part of
the index anyway).
Regards,
Clemens
_______________________________________________
sqlite-users mailing list
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users