本次主要介绍Adaptive rank-aware query optimization in relational databases论文中对rank join算子进行代价估计的部分。
Ilyas I F, Aref W G, Elmagarmid A K, et al. Adaptive rank-aware query optimization in relational databases[J]. ACM Transactions on Database Systems (TODS), 2006, 31(4): 1257-1304.
该文章讨论了关系型数据库上引入rank-join的查询计划,一个top-k的SQL的查询形如,
最简单的物理执行计划是先按照连接条件(join condition)来生成连接结果,之后再根据给定的函数计算每个匹配结果的分数,之后再根据分数排序获得前k个结果。这种方法叫做物化后排(materialize-then-sort),该方法代价最高的两部分是连接和排序。
为了解决这个瓶颈,一类rank join算子被提出,这类算子要求:输入的关系中至少一个是排序好的,并且输入关系要支持GetNext方法以顺序遍历结果,另外还需要分数的函数是聚合单调(aggregation monotone)的。这类方法有如下好处:
1)使得排序的操作可以下移到下层算子,甚至可以下推到存储系统
2)利用了输入关系的有序性来产生有序的输出结果
3)这类算子可以很好地跟已有算子组合
Rank join算子中效率较好的是Ilyas I F, Aref W G, Elmagarmid A K. 等2004年在VLDB会议上发表的Supporting top-k join queries in relational databases提出的HRJN算子。该算子的基本思想是估计没有未见的匹配结果的上界T,并且维护已匹配结果的第k大值
,当时可以输出top-k结果。如何估计这个T呢?我们用来表示我们从第i个输入关系中获得的最后结果,di表示我们从i个输入中已经获得的输入数。表示从第i个输入关系中获得的最大结果(也是第一个结果),那么我们把T估计为以下m个值中的最大值
当
时算法终止,输出top-k个结果。
接下来我们考虑一下rank join在查询计划中应该如何运用,
上图展示了三种利用了rank join的查询计划,第一种是R,S和T分别连接后最后排序得到top-k,中间的计划是R和S之间rank join得到的结果再和L进行rank join,最后一种是R跟S自然连接的结果排序后跟L进行rank join。R,S,L能否进行rank join取决于对应的属性上是否有索引支持按照属性的值顺序遍历。
Rank Join并不一定永远是占优的方案,论文中给了两种例子,在低join selectivity的情况下rank join的I/O代价可能会更大,另外,在k比较大的情况下,rank join也可能带来更大的代价。
接下来文章讨论了如何生成低代价的,同时又附带rank join的查询计划。生成计划的第一步是改进枚举的过程,使得带rank join的计划能被枚举出来,在基于DP的计划枚举器中,有一类引入了”interesting order”的概念,interesting的列指的是,当前阶段排序虽然会带来大代价,但之后的执行中可能有用的列。本文提出三种可以被考虑的情况:1)在join条件中出现的列,2)在groupby中出现的列 3)在orderby中出现的列。
我们考虑生成两表L和R的join计划的过程,若以下3种条件能满足一条,就考虑生成L和R的rank join计划:
1)在join的条件里有把L表的一个属性和R表的属性联系起来的操作
2)orderby函数F可以表达成
, 其中F1,F2,F3是三个评分函数, SL是由L表中属性产生的分数函数, SR是由R表中属性产生的分数函数, SO其余输入关系中的属性构成的分数函数。
3)至少有一个计划访问了L和/或R,并且访问时L按SL已排序和/或R按SR已排序.
参考图,我们可以观察到对于rank join算子,其代价有以下几个影响因素:
-
K的值,以及k传递过程中的变化,如图中,输出的k只有100,但是对于关系C而言,输出的k需要580
-
Rank join 算子输入关系本身的信息量(比如输入记录之间的分数差距等等),这会影响产生top-k结果所需要的访问数
-
连接操作本身的selectivity
在进行代价估计前,我们进行些假设,
-
连接操作的独立性(Join Independence)我们假设一对元组连接的可能性跟其它元组是否被选择进入rank join算子无关。
-
连接均匀性(Join Uniformity).我们假设L中的任一元组,其和R中任意元组连接成功的可能性是一样的,设为s。𝑃𝑟𝑜𝑏(𝐿_𝑖⋈𝑅_𝑗 )=𝑠
-
分数的分布。我们假设每个输入关系的分数分布都是标准可参数化的分布,如均匀分布,高斯分布,泊松分布等。
-
假设F是单调聚合的Monotonic Aggregation
以上两图是top-k 深度估计的算法框架,算法分为三个步骤。
第一步是估计any-k depth,即估计要产生k个结果(不一定要是top-k的结果)L表需要走的深度CL和R表需要走的深度CR,假设连接的selectivity为k,则需要
我们用SL(i)和SR(i)来表示L表的第i个输入的分数和R表的第i个输入的分数。
若满足
,且
,则top-k的结果在遍历到dL和dR时即可确认。
接下来我们看一个简单的例子来体验代价估计的原理。假设F函数为简单的求和,L和R满足均匀分布。我们用x表示L表平均下降的速度(比如L表中两个相邻项目差的平均值),用y表示R表平均下降的速度。那么,
的期望值是,的期望值是。
要获得最小的dL和dR,我们需要使得
最大化,这变成一个优化问题,问题的解由下列表达式给出
这只是最简单情况的一种估计,在数据分布不一致的情况下会带来高估或者低估的结果。这只是单个算子的情况,若多个rank join算子组成了一种层次的结构,那么最高层rank join算子输出结果的分数分布会趋近于正态分布,根据中心极限定理。
我们用表示up个分布的和,每个分布都是[0, n]上的均匀分布. 设L是l个有序关系rank-join之后的结果, 设R 是r个有序关系rank-join之后的结果. 简洁起见,设L和R都有n个元组,并且遵循和分布,则问题的最优解可以表示为
在这种估计框架下,错误会随着层数的增多而不断累加,因此作者提出了另外一种估计的框架。我们以
来表示关系rel里面第i个元组,用来表示第一个分数小于等于x的元组所处的位置,我们可以用以下两式估计dL和dR: