You should include both a and b in the index to be most helpful. CREATE INDEX whatever ON t (a, b);
However, you say that (a, b) is already the primary key and therefore this index already exists and you do not need to create another one. Although the index will contain all rows, finding the max(b) given an "a" value should take just 1 index lookup. If the optimizer does not do this for you (I believe it does) then you can just do: select b from t where a=:whatever order by b desc limit 1; to find the answer you seek with nothing more than a single lookup in the index. So lets test what SQLite is going to do: On SQLite 3.8.8 (head of trunk) we see that: SQLite version 3.8.8 2014-12-25 12:19:56 Enter ".help" for usage hints. Connected to a transient in-memory database. Use ".open FILENAME" to reopen on a persistent database. sqlite> create table t(a INTEGER, b INTEGER, primary key (a, b)); sqlite> insert into t values (1,1),(1,5),(2,3),(1,8),(2,7); sqlite> .explain sqlite> explain select max(b) from t where a=1; addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- -- ------------- 0 Init 0 21 0 00 Start at 21 1 Null 0 1 2 00 r[1..2]=NULL 2 OpenRead 1 3 0 k(3,nil,nil,nil) 00 root=3 iDb=0; sqlite_autoindex_t_1 3 Explain 0 0 0 SEARCH TABLE t USING COVERING INDEX sqlite_autoindex_t_1 (a=?) 00 4 Noop 0 0 0 00 Begin WHERE-loop0: t 5 Integer 1 3 0 00 r[3]=1 6 SeekLE 1 15 3 1 00 key=r[3] 7 IdxLT 1 15 3 1 00 key=r[3] 8 Noop 0 0 0 00 Begin WHERE-core 9 Column 1 1 4 00 r[4]=t.b 10 CollSeq 0 0 0 (BINARY) 00 11 AggStep 0 4 1 max(1) 01 accum=r[1] step(r[4]) 12 Goto 0 16 0 00 max() by index 13 Noop 0 0 0 00 End WHERE-core 14 Prev 1 7 0 00 15 Noop 0 0 0 00 End WHERE-loop0: t 16 Close 1 0 0 00 17 AggFinal 1 1 0 max(1) 00 accum=r[1] N=1 18 Copy 1 5 0 00 r[5]=r[1] 19 ResultRow 5 1 0 00 output=r[5] 20 Halt 0 0 0 00 21 Transaction 0 0 1 0 01 22 TableLock 0 2 0 t 00 iDb=0 root=2 write=0 23 Goto 0 1 0 00 sqlite> explain select b from t where a=1 order by b desc limit 1; addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- -- ------------- 0 Init 0 18 0 00 Start at 18 1 Noop 0 0 0 00 2 Integer 1 1 0 00 r[1]=1; LIMIT counter 3 OpenRead 2 3 0 k(3,nil,nil,nil) 00 root=3 iDb=0; sqlite_autoindex_t_1 4 Explain 0 0 0 SEARCH TABLE t USING COVERING INDEX sqlite_autoindex_t_1 (a=?) 00 5 Noop 0 0 0 00 Begin WHERE-loop0: t 6 Integer 1 2 0 00 r[2]=1 7 SeekLE 2 15 2 1 00 key=r[2] 8 IdxLT 2 15 2 1 00 key=r[2] 9 Noop 0 0 0 00 Begin WHERE-core 10 Column 2 1 3 00 r[3]=t.b 11 ResultRow 3 1 0 00 output=r[3] 12 IfZero 1 16 -1 00 r[1]+=-1, if r[1]==0 goto 16 13 Noop 0 0 0 00 End WHERE-core 14 Prev 2 8 0 00 15 Noop 0 0 0 00 End WHERE-loop0: t 16 Close 2 0 0 00 17 Halt 0 0 0 00 18 Transaction 0 0 1 0 01 19 TableLock 0 2 0 t 00 iDb=0 root=2 write=0 20 Goto 0 1 0 00 sqlite> So both forms of the query will run mostly the same plan and retrieve the result you desire in a single index lookup. --- Theory is when you know everything but nothing works. Practice is when everything works but no one knows why. Sometimes theory and practice are combined: nothing works and no one knows why. >-----Original Message----- >From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users- >boun...@sqlite.org] On Behalf Of Baruch Burstein >Sent: Monday, 29 December, 2014 01:34 >To: General Discussion of SQLite Database >Subject: [sqlite] Partial index to find maximum > >Hi, > >I have a table with a 2 column PK, say 'a' and 'b'. I need to find, for a >given value of 'a', the highest matching 'b'. The query itself it simple: > > SELECT max(b) FROM t WHERE a=:whatever > >To speed this up, I would add an index on 'a'. Now, the question is is >there some way to tell the index that I am only interested in the maximum >value of b? For example, for the following table: > >a|b >1|1 >1|2 >2|2 >2|3 > >I only need the index to contain the rows (1,2) and (2,3). The docs for >partial indexes say that they can't contain functions (like max()). Any >suggestions? > >-- >˙uʍop-ǝpısdn sı ɹoʇıuoɯ ɹnoʎ 'sıɥʇ pɐǝɹ uɐɔ noʎ ɟı >_______________________________________________ >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