On Friday, 9 May 2014, RSmith <rsm...@rsweb.co.za> wrote: > > On 2014/05/08 18:16, Woody Wu wrote: > >> On 2014年5月8日 GMT+08:00PM11:59:33, RSmith <rsm...@rsweb.co.za> wrote: >> >>> On 2014/05/08 14:13, Woody Wu wrote: >>> >>>> Do you mean that my index for this case is already the best choice? >>>> >>>> And, as a general question, for a query in the form of >>>> select max(a) from table where a < InF and b=B and c=C. >>>> what's the best index in the case of (1) B is an existed one, or (2) >>>> >>> B is not exists ? >>> >>> Imagine you have a table like this: >>> >>> A, B, C >>> 1, 1, 1 >>> 2, 1, 2 >>> 3, 2, 1 >>> 4, 1, 3 >>> 5, 1, 1 >>> 6, 2, 1 >>> 7, 1, 2 >>> >>> etc. >>> >>> >> Thanks Smith, you explained quite clear in your way. I understood that >> things has to be that if sqlite could only work like that. >> >> What I was wondering is that why sqlite couldn't find out earlier that >> b=8 c=1 denotes an empty set? If I run something like "select * from table >> where b=8 and c=1", it could return very quickly. If so, the max(a) on an >> empty set should alway be Null. Am I thinking right? >> >> >> -Woody Wu >> > > It makes no sense if there isn't some index defined on b or c or both. If > there is, then it is the same happy accident accident looked at in a > different way. The reason that the query returns fast if you "Just" do > WHERE b=8 AND c=1 is that there is either an automatic or explicit index on > column b and/or c - but - as soon as you change the query to include > grouping (i.e: max(a)) then that specific index is no longer the best one > to use - and you cannot expect SQLite to first run some other arbitrary > "test" query to see if it has no results, and only THEN try your whole > query after it "knows" whether the other model query has actual results or > not. Put another way, you CAN construct an Index that will be VERY fast for > queries where there definitely is NO value in the list, consider again the > table from earlier: > > A, B, C > 1, 1, 1 > 2, 1, 2 > 3, 2, 1 > 4, 1, 3 > 5, 1, 1 > 6, 2, 1 > 7, 1, 2 > > Now add Index (B, C, A) - a covering Index which first lists B and C, then > A... now if you were to ask of it: > > SELECT max(a) from table where a<INF AND b=8 and c=1; > > It will start by scanning the new Index for values where b=8... and Not > find any, so very quickly return with no results. > > but now let's say you change the query to: > > SELECT max(a) from table where a<INF AND b=1 and c=1; > > It starts (as before) scanning the table (assuming it uses the new index - > this is not a given) and finds that the very first entry indeed b=1 and > c=1.. so it checks a<inf which is also true... nice, but that's only the > first check, max(a) requires we scan all other values to find the max of a, > at least all values where b=1 and c=1.. of which there might be very very > many meaning this query is a LOT slower now than NOT using that index (as > you had it in your original post when you get very fast results). > > So the new Index is optimized to be quick when the b value DOESN'T exist, > but slow when it DOES... and the original index is better to use if the b > value DOES exist, but slow when it DOESN'T. Again, there is no best index > that will satisfy both those requirements. Simon's advice is still best re > making Indices and then running Analyze to see which queries get used, and > whether they have good times, then removing the bad ones. > > If there is a way you could tell before-hand whether a value exists or > not, that would be better, and nothing stoppping you from actually running > two queries every time, first check if it exists, then, if it does, run the > second query that is faster (as the original). - Actually this might make > your unique problem into the fastest possible results, but testing is > needed to verify and it isn't a solution you can short-hand off to the > Query planner... you need to do two queries. > > > _______________________________________________ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users >
Simon, After the explanation, I understand the problem so much better than before. I think I would to use the two queries solution. Thanks a lot! -- Life is the only flaw in an otherwise perfect nonexistence -- Schopenhauer narke public key at http://subkeys.pgp.net:11371 (narkewo...@gmail.com) _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users