I get confusing (to me) results when toying with a query that I think should use a partial index as a "covering index". This is using sqlite 3.20.1 on Arch Linux x86_64.
The examples listed below start from a new, empty database. *** Given a table and an index like this CREATE TABLE tab (x1 TEXT, x2 TEXT, x3 TEXT, x4 TEXT, PRIMARY KEY (x1, x3) ) WITHOUT ROWID; CREATE INDEX ind ON tab (x2, x4) WHERE x4 IS NULL; i get the result I would expect: The index is used as a "covering index", even though if I read the bytecode correctly there's a != NULL comparison that's not strictly necessary, but that would be just room for further optimization: sqlite> EXPLAIN QUERY PLAN SELECT x1, x2 FROM tab WHERE x4 IS NULL; selectid|order|from|detail 0|0|0|SCAN TABLE tab USING COVERING INDEX ind sqlite> EXPLAIN SELECT x1, x2 FROM tab WHERE x4 IS NULL; addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- -- ------------- 0 Init 0 10 0 00 Start at 10 1 OpenRead 1 3 0 k(4,,,,) 00 root=3 iDb=0; ind 2 Rewind 1 9 1 0 00 3 Column 1 1 1 00 r[1]=tab.x4 4 NotNull 1 8 0 00 if r[1]!=NULL goto 8 5 Column 1 2 2 00 r[2]=tab.x1 6 Column 1 0 3 00 r[3]=tab.x2 7 ResultRow 2 2 0 00 output=r[2..3] 8 Next 1 3 0 01 9 Halt 0 0 0 00 10 Transaction 0 0 2 0 01 usesStmtJournal=0 11 Goto 0 1 0 00 *** But if I remove the (redundant) column x4 from the index, it seems to me like it's no longer used as a "covering index" for the same query, even though all the output columns are still there and the index *is* actually used: DROP TABLE tab; CREATE TABLE tab (x1 TEXT, x2 TEXT, x3 TEXT, x4 TEXT, PRIMARY KEY (x1, x3) ) WITHOUT ROWID; CREATE INDEX ind ON tab (x2) WHERE x4 IS NULL; sqlite> EXPLAIN QUERY PLAN SELECT x1, x2 FROM tab WHERE x4 IS NULL; selectid|order|from|detail 0|0|0|SCAN TABLE tab USING INDEX ind sqlite> EXPLAIN SELECT x1, x2 FROM tab WHERE x4 IS NULL; addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- -- ------------- 0 Init 0 14 0 00 Start at 14 1 OpenRead 0 2 0 k(2,,) 00 root=2 iDb=0; tab 2 OpenRead 1 3 0 k(3,,,) 00 root=3 iDb=0; ind 3 Rewind 1 13 1 0 00 4 Column 1 1 1 00 r[1]= 5 Column 1 2 2 00 r[2]= 6 NotFound 0 12 1 2 00 key=r[1..2] 7 Column 0 3 3 00 r[3]=tab.x4 8 NotNull 3 12 0 00 if r[3]!=NULL goto 12 9 Column 1 1 4 00 r[4]=tab.x1 10 Column 1 0 5 00 r[5]=tab.x2 11 ResultRow 4 2 0 00 output=r[4..5] 12 Next 1 4 0 01 13 Halt 0 0 0 00 14 Transaction 0 0 47 0 01 usesStmtJournal=0 15 Goto 0 1 0 00 *** It gets even more confusing: If I remove the "TEXT" type from columns x3 and x4, the index isn't used at all: DROP TABLE tab; CREATE TABLE tab (x1 TEXT, x2 TEXT, x3, x4, PRIMARY KEY (x1, x3) ) WITHOUT ROWID; CREATE INDEX ind ON tab (x2) WHERE x4 IS NULL; sqlite> EXPLAIN QUERY PLAN SELECT x1, x2 FROM tab WHERE x4 IS NULL; selectid|order|from|detail 0|0|0|SCAN TABLE tab *** Except if I also remove the "TEXT" type from column x2, the index is used again: DROP TABLE tab; CREATE TABLE tab (x1 TEXT, x2, x3, x4, PRIMARY KEY (x1, x3) ) WITHOUT ROWID; CREATE INDEX ind ON tab (x2) WHERE x4 IS NULL; sqlite> EXPLAIN QUERY PLAN SELECT x1, x2 FROM tab WHERE x4 IS NULL; selectid|order|from|detail 0|0|0|SCAN TABLE tab USING INDEX ind *** But only until I also remove the "TEXT" type from column x1, then it's not used: DROP TABLE tab; CREATE TABLE tab (x1, x2, x3, x4, PRIMARY KEY (x1, x3) ) WITHOUT ROWID; CREATE INDEX ind ON tab (x2) WHERE x4 IS NULL; sqlite> EXPLAIN QUERY PLAN SELECT x1, x2 FROM tab WHERE x4 IS NULL; selectid|order|from|detail 0|0|0|SCAN TABLE tab Is this the expected behaviour? Thanks! Martin _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users