通过sqlite文档阅读我发现了以下函数:
http://www.sqlite.org/lang_corefunc.html#likelihood
似然(X,Y)函数返回参数X不变。似然值Y(X,Y) 必须是0.0到1.0之间的浮点常数,包括0.0和1.0。似然(X)函数 是代码生成器优化掉的无操作,因此它不会消耗CPU周期 运行时(即,在调用sqlite3_step()期间)。可能性的目的(X,Y) function是为查询规划器提供一个提示,即参数X是一个布尔值 大概为Y的概率为真。不太可能的(X)函数是短手的 似然性(X,0.0625)。
假设我知道1将返回75%的时间,那将会如何:
select likelihood(x,.75)
帮助查询优化器?
答案 0 :(得分:8)
original example是这样的:
考虑以下架构和查询:
CREATE TABLE composer( cid INTEGER PRIMARY KEY, cname TEXT ); CREATE TABLE album( aid INTEGER PRIMARY KEY, aname TEXT ); CREATE TABLE track( tid INTEGER PRIMARY KEY, cid INTEGER REFERENCES composer, aid INTEGER REFERENCES album, title TEXT ); CREATE INDEX track_i1 ON track(cid); CREATE INDEX track_i2 ON track(aid); SELECT DISTINCT aname FROM album, composer, track WHERE cname LIKE '%bach%' AND composer.cid=track.cid AND album.aid=track.aid;
该模式适用于(简化的)音乐目录应用程序,但在其他情况下会出现类似的模式。有很多专辑。每个专辑包含一个或多个曲目。每首曲目都有一个作曲家。每个作曲家可能与多个曲目相关联。
查询会询问包含曲目的每张专辑的名称,该曲目的名称与'%bach%'匹配。
查询计划程序需要在此查询的几种备选算法中进行选择。最佳选择取决于表达式“cname LIKE'%bach%'”过滤结果的程度。让我们给这个表达式一个“过滤值”,这是一个介于1.0和0.0之间的数字。值为1.0表示对于composer表中的每一行,cname LIKE'%bach%'为true。值为0.0表示表达式永远不会为真。
当前的查询规划器(版本3.8.0)假定过滤器值为1.0。换句话说,它假定表达式始终为true。规划人员假设最坏的情况,以便选择一个最小化最坏情况运行时间的计划。这是一种安全的方法,但它不是最佳的。为1.0过滤器选择的计划是track-album-composer。这意味着“轨道”表位于外循环中。对于每一首曲目,在专辑上进行索引查找。然后在composer上进行索引查找,然后运行LIKE 表达式以查看是否应输出相册名称。
更好的计划是track-composer-album。如果LIKE 表达式为false,则第二个计划会避免相册查找。如果过滤器值略小于1.0,则当前规划器将选择第二种算法。说0.99。换句话说,如果规划器认为LIKE 表达式对于每100行中的1行是假的,那么它将选择第二个计划。这是过滤器值很大时的正确(最快)选择。
但是在音乐库的常见情况下,过滤器值可能比1.0更接近0.0。换句话说,在大多数作曲家名称中不太可能找到字符串“bach”。对于接近0.0的值,最好的计划是composer-track-album。作曲家 - 曲目 - 专辑计划是一旦查找匹配'%bach%'的条目就扫描作曲家表,并且每个匹配的条目使用索引来查找曲目然后查找专辑。当前的3.8.0查询计划器选择此当滤波器值小于约0.1时的第三个计划。
likelihood
函数为数据库提供了(希望)对滤波器选择性的更好估计。
使用示例查询,它看起来像这样:
SELECT DISTINCT aname
FROM album, composer, track
WHERE likelihood(cname LIKE '%bach%', 0.05)
AND composer.cid=track.cid
AND album.aid=track.aid;