【发布时间】:2015-11-07 21:31:32
【问题描述】:
我已将性能问题缩小到如下所示的特定 SQLite 查询:
select *
from test
where (?1 is null or ident = ?1)
and (?2 is null or name = ?2)
and (?3 is null or region = ?3);
这允许输入参数的任何子集(超过三个)使用单个查询。不幸的是,在此使用 explain query plan 会产生:
1|0|0|SCAN TABLE test
所以无论传入什么,SQLite 都会读取整个表。
将查询更改为from table indexed by test_idx 会导致它失败:Error: no query solution。
删除?1 is null or 会产生更有利的查询:
1|0|0|SEARCH TABLE test USING INDEX idx (ident=?)
但是,请注意只能使用一个索引。将扫描ident 的所有匹配项以查找与其他字段的匹配项。使用包含所有匹配字段的单个索引可以避免这种情况:
0|0|0|SEARCH TABLE test USING INDEX test_idx_3 (ident=? AND region=? AND name=?)
认为SQLite's query planner 能够消除或简化每个条件以进行简单的索引列检查似乎是合理的,但显然情况并非如此,因为查询优化发生在参数绑定之前,并且不会发生进一步的简化.
显而易见的解决方案是有 2^N 个单独的查询,并在运行时根据要检查的输入组合选择合适的查询。对于 N=2 或 3,这可能是可以接受的,但在这种情况下绝对不可能。
当然,有很多方法可以重新组织数据库,使这种类型的查询更加合理,但假设这也不实用。
那么,我怎样才能搜索表中的任何列子集,而不会失去这些列上索引的性能优势?
【问题讨论】:
-
一问一答?
-
@lad2025 是的,它一直受到鼓励,我不确定它是什么时候添加的,但现在可以选择同时组合它们。 http://stackoverflow.com/help/self-answer
-
我知道你可以回答自己的问题。但是我不知道你是否需要帮助
-
@TimSylvester 我有点不清楚你到底在这里绑定了什么。如果它是文字,那么您不会事先知道它是否为 null 或不使
?1 is null部分不必要吗?占位符是否要被列名替换?
标签: indexing sqlite combinations