Solr区间查询背后原理

来源:互联网 发布:欧楷笔法 知乎 编辑:程序博客网 时间:2024/06/06 01:54

Solr使用TrieTree对区间查询进行加速优化。

  • TrieTree帮助加速区间查询的原理

       以十进制区间查询为例,假设我们有421,423...642,644等数据,每个数据都对应了若干个实例,如果我们想统计423~642的总实例数量,最常想到的方法是遍历423到642每个书,并将实例个数相加。但这样做如果数据范围很大,那么累加的次数会很大。而如果要做m次这样的统计,那么运算量会是m倍。

这样看要提升效率,我们应该试图降低每次统计的累加次数。如果使用TrieTree对数据进行预处理,可以显著降低每次统计的累加次数。

       首先以十进制数位(个十百千万)进行TrieTree变形得到如下树:


       其次,上层树生成式,要将下层节点的累加数缓存到这层各自节点。比如,假设421有3个实例,423有2个实例,那么42这个节点要将3+2=5缓存到自身。

假设节点k的实例个数,我们记为N(k), 这样一来,如果我们要计算423~642的实例总数,我们只要做如下运算N(423)+N(44)+N(5)+N(63)+N(641)+N(642),这样从11次累加降到了6次累加。

  • 对于solr应用:

      上面这个例子是按照“个十百千”对数据进行TrieTree转换,solr是以二进制进行转换,可以设置参数precisionStep。举个例子,假设三个数(二进制)11001000,11000100,11011100, 11011101,如果precisionStep=4,那么转化为TrieTree为:


       如果我们要查询第2~4号数的对应的实例的数量,那么计算N(1101)+N(11000100)。

       那么我们怎么知道要将N(1101)和N(11000100)相加呢,其实这就是solr在searchtime时的一个算法,有一篇博文总结的很好:

查找的过程(precisionStep = 8),注意开区间和闭区间的设定:
1、将查找的范围A~B的上下界A、B值,取出最高8位,标记为A1、B1,到第一段(Tree的第一层)找在(A1~B1)内的term,得到需要查找的termlist1
2、继续取A、B值的最高16位,标记为A2、B2,到第二段来查在(A2~A1 11111111]和[B1 11111111,B2)范围内的Term,得到termlist2
3、继续取A、B值的最高24位,标记为A3、B3,到第三段来查在(A3~A2 11111111]和[B2 11111111,B3)范围内的Term,得到termlist3
4、继续取A、B值的最高24位,也即A、B值,到第四段来查找[A~A3 11111111]和[B3 11111111,B]范围内的Term,得到termlist4
5、最后查询这些term,归并,就得到了符合查询条件的docid了。从上面的描述,我们可以看到,需要查询的term最多为254+255*2+255*2+256*2=1786个,传统的方式A~B个term要小的多,因此性能有很大的提升。

                                                       

原创粉丝点击