我希望通过树路径从表中获取子树。
path
列存储字符串,如:
foo/
foo/bar/
foo/bar/baz/
如果我尝试选择以某条路径开头的所有记录:
EXPLAIN QUERY PLAN SELECT * FROM f WHERE path LIKE "foo/%"
它告诉我即使path
列被编入索引,也会扫描该表:(
有什么方法可以让LIKE使用索引而不扫描表吗?
我找到了一种方法来实现我想要的闭包表,但是它更难维护,写入速度非常慢......
答案 0 :(得分:3)
LIKE
具有严格的要求,可以使用索引(ref)进行优化。
如果您可以稍微放松一下您的要求,您可以使用词典排序来获取索引查找,例如
SELECT * FROM f WHERE PATH >= 'foo/' AND PATH < 'foo0'
其中0
是/
之后的词典下一个字符。
如果满足优化要求,这与优化程序对LIKE
的优化基本相同。
答案 1 :(得分:3)
为了能够在SQLite中使用LIKE索引,
索引必须声明为COLLATE NOCASE(直接或因为该列已声明为COLLATE NOCASE):
> CREATE TABLE f(path TEXT);
> CREATE INDEX fi ON f(path COLLATE NOCASE);
> EXPLAIN QUERY PLAN SELECT * FROM f WHERE path LIKE 'foo/%';
0|0|0|SEARCH TABLE f USING COVERING INDEX fi (path>? AND path<?)
可以使用case_sensitive_like PRAGMA删除第二个限制,但这会改变LIKE的行为。
或者,可以使用LIKE 'foo/%'
替换GLOB 'foo/*'
来使用区分大小写的比较。