Paul Vercellotti wrote:
> I've got a very slow query that seems to be oh-so-close to running
> quickly, and it seems to come down to handling of OR operators.
> When the query has one OR criteria, it uses the correct indexes, but
> when there are two, it does a table scan, which in this case brings
> the query time from milliseconds up to minutes in length when the
> database is large (~3GB).   I don't understand why it thinks it needs
> a table scan

The _estimated_ cost for executing the ORs separately is higher than
that for single table scan.

> 0|0|1|SCAN TABLE search_hierarchy (~1000000 rows)

You did not run ANALYZE.
<http://www.sqlite.org/lang_analyze.html>

> Are there any suggestions to eliminate the table scan in the original
> query, since it seems quite capable of efficiently handling each of
> the OR expressions on their own.

Try to put the FTS matches into a subquery (this is usually done to
avoid inefficient joins with the FTS tables):

EXPLAIN QUERY PLAN
SELECT files.key FROM files, search_hierarchy
WHERE search_hierarchy.child = files.parent AND
( search_hierarchy.parent = 12 OR files.parent = 12 ) AND
(files.key IN (SELECT rowid FROM filename_fts WHERE file_name_fts MATCH '"X*"' 
UNION
               SELECT rowid FROM file_comment_metadata WHERE fileComment MATCH 
'"X*"'));

0|0|0|SEARCH TABLE files USING INTEGER PRIMARY KEY (rowid=?) (~25 rows)
0|0|0|EXECUTE LIST SUBQUERY 1
2|0|0|SCAN TABLE filename_fts VIRTUAL TABLE INDEX 2: (~0 rows)
3|0|0|SCAN TABLE file_comment_metadata VIRTUAL TABLE INDEX 2: (~0 rows)
1|0|0|COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)
0|1|1|SEARCH TABLE search_hierarchy USING INDEX search_hierarchy_child_idx 
(child=?) (~5 rows)

> (I could do a UNION of multiple versions of the whole query with each
> OR section separated out, but that's not terribly satisfying.)

Replacing this UNION with OR does not appear to help (I guess the other
OR interferes too much):

EXPLAIN QUERY PLAN
SELECT files.key FROM files, search_hierarchy
WHERE search_hierarchy.child = files.parent AND
( search_hierarchy.parent = 12 OR files.parent = 12 ) AND
(files.key IN (SELECT rowid FROM filename_fts WHERE file_name_fts MATCH '"X*"') 
OR
 files.key IN (SELECT rowid FROM file_comment_metadata WHERE fileComment MATCH 
'"X*"'));

0|0|0|EXECUTE LIST SUBQUERY 1
1|0|0|SCAN TABLE filename_fts VIRTUAL TABLE INDEX 2: (~0 rows)
0|0|0|SEARCH TABLE files USING INTEGER PRIMARY KEY (rowid=?) (~25 rows)
0|0|0|EXECUTE LIST SUBQUERY 2
2|0|0|SCAN TABLE file_comment_metadata VIRTUAL TABLE INDEX 2: (~0 rows)
0|0|0|SEARCH TABLE files USING INTEGER PRIMARY KEY (rowid=?) (~25 rows)
0|0|0|EXECUTE LIST SUBQUERY 3
3|0|0|SCAN TABLE filename_fts VIRTUAL TABLE INDEX 2: (~0 rows)
0|0|0|EXECUTE LIST SUBQUERY 4
4|0|0|SCAN TABLE file_comment_metadata VIRTUAL TABLE INDEX 2: (~0 rows)
0|1|1|SEARCH TABLE search_hierarchy USING INDEX search_hierarchy_child_idx 
(child=?) (~5 rows)


Regards,
Clemens
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to