Re: speeding up an FTS5 search with a JOIN
Dan Kennedy <[email protected]> Sat, 7 Mar 2020 20:32:54 +0700
| Newsgroups | gmane.comp.db.sqlite.general |
|---|---|
| Message-ID | <[email protected]> |
On 7/3/63 14:58, P Kishor wrote: > I asked this question on Stackoverflow with not much success, and a suggestion to ask it on the list. So here I am. I have two tables, t1(id, t1Id, … other cols …, fullText) and a FTS5 virtual table vt1(t1Id, fullText) > > ``` > sqlite> EXPLAIN QUERY PLAN > ...> SELECT Count(*) as num FROM t1 WHERE deleted = 0; > > QUERY > PLAN > --SEARCH TABLE t1 USING COVERING INDEX ix_t1_t1Id (deleted=?) > > sqlite> SELECT Count(*) as num FROM t1 WHERE deleted = 0; > 308498 > > Run Time > : real 0.043 user 0.023668 sys 0.009005 > ``` > > > As can be see above, the actual query takes ~43ms > > ``` > sqlite> EXPLAIN QUERY PLAN > ...> SELECT Count(*) as num FROM vt1 WHERE vt1 MATCH 'foo'; > > QUERY > PLAN > --SCAN TABLE vt1 VIRTUAL TABLE INDEX 131073: > > sqlite> SELECT Count(*) as num FROM vt1 WHERE vt1 MATCH 'foo'; > 80789 > > Run Time > : real 0.047 user 0.008021 sys 0.009640 > ``` > > The actual query, in this case, takes ~47ms. So far so good. But the problem occurs when I join the two tables > > ``` > sqlite> EXPLAIN QUERY PLAN > ...> SELECT Count(*) as num > ...> FROM t1 JOIN vt1 ON t1.t1Id = vt1.t1Id > ...> WHERE t1.deleted = 0 AND vt1 MATCH 'foo'; > > QUERY > PLAN > |--SCAN TABLE vt1 VIRTUAL TABLE INDEX 0:m > --SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (t1Id=?) > > sqlite> SELECT Count(*) as num > ...> FROM t1 JOIN vt1 ON t1.t1Id = vt1.t1Id > ...> WHERE t1.deleted = 0 AND vt1 MATCH 'foo'; > 80789 That does seem slow. Are there many rows in table "t1" with t1.deleted set to something other than 0? What does: SELECT count(*) AS num FROM t1 JOIN vt1 ON t1.t1Id=vt1.t1Id WHERE vt1 MATCH 'foo'; return? Dan. > > Run Time > : real 26.218 user 1.396376 sys 5.413630 > ``` > > The answer is correct but the query takes more than 26 seconds! Of course, I would like to speed up this query by several orders of magnitude, but I would also like to understand why this join is causing the slowdown. > > Now, the reason I have constructed a query like this is because users can add further constraints for the table t1. For example, > > ``` > sqlite> SELECT Count(*) as num > ...> FROM t1 JOIN vt1 ON t1.t1Id = vt1.t1Id > ...> WHERE t1.deleted = 0 AND > ...> WHERE t1.frob = ‘bar' AND > ...> WHERE t1.nob = ‘baz' AND > ...> vt1 MATCH 'foo’; > ``` > > Also, in every operation, for every given constraint, two queries are performed, one that returns the count and the other that returns the actual columns. And, finally, only a subset of the results are returned using LIMIT and OFFSET but *after* a sort ORDER has been prescribed. So, in reality, the last constraint above would result in the following > > ``` > sqlite> SELECT Count(*) as num > ...> FROM t1 JOIN vt1 ON t1.t1Id = vt1.t1Id > ...> WHERE t1.deleted = 0 AND > ...> WHERE t1.frob = ‘bar' AND > ...> WHERE t1.nob = ‘baz' AND > ...> vt1 MATCH 'foo’; > 20367 > > sqlite> SELECT t1.id, t1.t1Id, … other cols …, > ...> snippet(vt1, 1, "<b>", "</b>", "", 50) AS context, > ...> FROM t1 JOIN vt1 ON t1.t1Id = vt1.t1Id > ...> WHERE t1.deleted = 0 AND > ...> WHERE t1.frob = ‘bar' AND > ...> WHERE t1.nob = ‘baz' AND > ...> vt1 MATCH ‘foo’ > ...> ORDER BY <some t1 col> > ...> LIMIT 30 OFFSET <some offset calculated by pagination>; > ``` > > When no t1 columns are prescribed in the constraint, the default count (shown above) and default cols are returned with the FTS search > > ``` > sqlite> SELECT Count(*) as num > ...> FROM t1 JOIN vt1 ON t1.t1Id = vt1.t1Id > ...> WHERE t1.deleted = 0 > ...> vt1 MATCH 'foo’; > 20367 > > sqlite> SELECT t1.id, t1.t1Id, … other cols …, > ...> snippet(vt1, 1, "<b>", "</b>", "", 50) AS context, > ...> FROM t1 JOIN vt1 ON t1.t1Id = vt1.t1Id > ...> WHERE t1.deleted = 0 > ...> vt1 MATCH ‘foo’ > ...> ORDER BY <some t1 col> > ...> LIMIT 30 OFFSET 0; > ``` > _______________________________________________ > sqlite-users mailing list > [email protected] > http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users _______________________________________________ sqlite-users mailing list [email protected] http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users