crystal 分组计算记录行数_利用关联采样估算 join 的结果行数

本文介绍了SQL查询中Join结果行数估算的重要性,并对比了基于直方图和采样方法的优缺点。关联采样作为一种改进的估算策略,通过线下和线上两个阶段进行数据采样,提高了估算准确性。文章详细阐述了CSDL(Discrete Learning)模型及其优势,包括针对不同数据分布的采样策略和discrete learning算法,旨在解决现有方法的局限性,提供更精确的Join结果估算。
摘要由CSDN通过智能技术生成

本文是对论文 “Improved Correlated Sampling For Join Size Estimation” 的阅读个人总结,如有不当之处请指正。

问题是什么?

对 SQL 查询的结果行数做估算在基于代价的查询优化中是非常重要的一个步骤。以如下查询为例:

SELECT * FROM t1 JOIN t2 ON t1.a = t2.a AND t1.b = t2.b WHERE t1.c > 1 and t2.c > 1;

在考虑两张表的索引选择,以及 join 的算法选择时,需要较为准确估算查询在每个步骤后剩余的结果行数,这里的步骤主要包括选择和连接操作。相比于估算单表上的选择结果行数,准确估算多表 join 的结果行数会更困难。

目前主流的估算 join 结果行数的方法可以划分为两类:

  1. 基于直方图的估算方法,利用统计信息和均匀分布 / 独立性假设计算结果行数;
  2. 基于采样的估算方法,在小规模的独立采样数据集上执行查询的步骤,利用得到的结果行数反推真实结果行数;

基于直方图的估算方法主要有两大缺陷:

  1. 在 join key 的数量上扩展性不好,主要体现在两个方面:第一是随着 join key 数量和查询复杂度的增加,存储和推导直方图的代价会变得很高;第二是在多维直方图上准确估算 join 结果行数的计算公式会变得很复杂;
  2. 直方图主要针对的是固定前缀的范围查询估算,对于一些选择谓词的估算起不到作用,比如 t1.c like ‘%hello%’ 这样的选择条件无法用直方图做出估算;

基于采样的估算方法可以规避上述基于直方图方法的两个缺陷,但也有其自己的问题:由于两张表的采样是独立的,忽略了表之间的 join 关系,导致估算准度不高。近年来,一种新的基于关联采样的 join 结果行数估算方法被提出,用来弥补简单采样策略的缺陷。

什么是关联采样?

关联采样分为线下和线上两个阶段,对于 A 和 B 两张表的连接 A ⋈ B:

  1. 线下阶段会首先从 A 表中以概率 p 随机抽样记录,构造出 A 的抽样
    ,然后计算出 B 和
    的 semi join 结果,即 B ⋉
    ,再从这个 semi join 结果集中采样,构造出 B 的抽样
    。显而易见,
    中的每一条记录,都可以和
    中的一条或多条记录连接。
  2. 在线上阶段,对于带具体过滤条件的两表连接 A ⋈ B,首先在
    上应用具体的过滤条件,得到过滤后的采样
    ,然后对
    做连接操作,得到过滤后的采样的 join 结果行数 |
    |,最后将这个结果除以概率 p 作为真实数据集上的 join 结果行数估算。

目前业界提出了多种关联采样的变种,在一些细节步骤上做了优化,并且都证明了相比于简单采样策略的方法会有更准确的估算结果,其中被普遍认可的一个变种是「两步关联采样 CS2L」,其主要优化是精心选取了采样概率,来最小化估算的方差。但 CS2L 这种方法有如下三个缺陷:

  1. 当过滤后的采样集合
    很小时,估算准度很差;
  2. 当 join key 上数据倾斜严重时,估算准度很差;
  3. 计算最优的采样概率复杂度很高,并且没有公认的解决方案;

本篇论文着眼在用关联采样估算 join 结果,并解决现有关联采样方法的一些问题。主要的贡献点在于:

  1. 用一个模型囊括了现有的所有关联采样变种方法;
  2. 通过模型发现了现有变种的盲区,提出了一种新的变种 CSDL;
  3. 进一步发现了一个混合变种方法 CSDL-opt,在不同数据分布时用不同的采样策略;实验证明 CSDL-opt 具有最好的效果;

模型长什么样?

模型试图从 5 个维度,或者说用 5 个变量来描述一个具体的关联采样方法:

  1. 概率 p:如果将 A 表的 join key 上的取值去重后的集合记作
    ,从
    中采样出一个子集 V ⊆
    ,则 p 表示
    中每一个值能进入 V 的概率;
  2. 概率 q:在构造 A 表的采样
    时,对 A 表中的每一行记录,首先判断该行 join key 的值是否在 V 中,如果不在,则跳过该行记录;如果在,则该行以概率 q 进入到最终采样
    中;
  3. 概率 u:在构造 B 表的采样
    时,首先计算 semi join 的结果 B ⋉
    ,结果里的每行记录以概率 u 进入到最终采样
    里;
  4. 估算方法:即如何用根据采样算出的 join 结果行数反推真实的 join 结果行数,目前所有的关联采样变种都是用的叫 scaling up 的估算方法,即将采样算出的 join 结果除以上述的概率:

e8b30c9fc88027b036c85a90919a2f27.png

其中,

表示 v 在
中出现的频次,
表示 A 表 和 B 表中所有 join key 值的交集;

5. 是否使用 sentry:所谓的 sentry 是指在构造 S_A 和 S_B 时,在考虑概率 q 和 u 之外,保证该 join key 值的记录至少有一行被采样进 S_A 和 S_B,这样可以避免某些 join key 取值的频次较小导致无法出现在采样里;在应用了 sentry 优化后,估算公式应当调整为:

5b490b1094bcfaf520842963738a6bab.png

套用这个模型,现有较为知名的三种关联采样变种方法可以被描述为:

  • CS2
    • 对于所有的 join key 取值,p 都取 1,q 都取 θ(这里 θ 是用户预先定义的对采样集合的大小限制,具体地说,θ 是采样集合相对于原数据集比例的上限),u 都取 1,不使用 sentry,即估算是用的上述 4 中的公式;
    • 行为上描述起来就是直接对 A 表用概率 θ 采样构造
      ,用 B ⋉
      整个作为
    • 这种方法的缺陷就是 B ⋉
      的大小是不可预期的,一般来说都满足不了用户指定的对采样大小的 θ 限制;
  • CSO
    • 对于所有的 join key 取值,p 都取 θ,q 和 u 都取 1,不使用 sentry,即估算也是用的上述 4 中的公式;
    • 这种方法的缺陷是对于某个 join key 取值,其在采样中的存在是 all or nothing 的状态,即要么没有一行在采样中,要么所有行都在采样中,会导致不同估算的准确度的方差很大,即如果选择条件过滤掉了不在采样中的行,join 结果的估算会比较准,而如果选择条件不能过滤掉不在采样中的行,join 结果的估算就很不准;
  • CS2L
    • 对于不同的 join key 取值 v,p 取不同的值;如果用
      分别表示某个 join key 取值 v 在 A 表和 B 表中出现的频次,则 p 对不同 v 取值不同且等比于 sqrt(
      *
      ),即如果 v 对于 join 结果集贡献越大,将它采样进 V 的概率就越大;对于所有的 join key 值,q 和 u 取相同的小于 1 的一个值,具体的值为多少由表里的数据分布决定,如果将它当作一个变量,可以用一个包含这个变量的公式计算出不同估算的准确度的方差,以最小化这个方差为目标,可以求解出这个具体的 q 和 u 值;这个方法使用 sentry,所以其估算使用的是上述 5 中的公式;
    • 这种方法的缺陷是计算出能最小化估算方差的 q 和 u 值的复杂度很高,没有一个公认的解决方案;

除了上述列举的缺陷,以上三种方法还有如下两点共同不足:

  1. 当采样数据集很小时,估算准确度都不高;而关联采样需要对每个 join graph(即表的连接组合方式) 中的每张表做一次采样并存储采样,这就要求采样数据集要尽可能小;
  2. 以上三种方法都是固定的采用一种采样策略,忽略了对数据分布特点的考虑,而论文通过实验观察到,不同数据分布下适用的最佳采样策略其实是不同的;

结合这些已有方法的缺陷,以及上述总结出来的模型,论文提出了一种新的关联采样方法 CSDL。

什么是 CSDL ?

可以用以上的模型来宏观描述 CSDL 为:

  • 针对不同的数据分布特点,采用不同的 p, q 和 u 取值;
  • 用一个叫做 discrete learning 的算法作为估算方法,而不是现有方法都在适用的 scaling up;discrete learning 算法可以通过很小的采样数据集准确地学习到一个离散分布,这个分布进而会被用作估算;
  • 使用了 sentry 技术;

可以看到,针对上面提到的已有方法的缺陷,CSDL 都相应给出了解决方案。

Discrete Learning

首先介绍下 discrete learning 算法,该算法是用在线上阶段,根据采样

估算出 A 表中 join key 取值的分布。该算法是借鉴的另一篇论文的成果[1],所以在本篇论文中并没有给出太详细的介绍。从直观上可以简单理解为:给定一个数据分布(比如二项分布),我们可以预估出它的一个采样是什么样子的;现在将给定的输入换做是一个具体的采样,这时候我们需要估算一个最优的数据分布,使得从该分布估算出来的采样和输入的采样尽可能接近。如何描述两个采样是否相似?论文定义了采样的指纹
,表示采样中出现 i 次的值有多少个,不同 i 对应的
一起就构成了一个直方图,通过将两个采样的不同 i 值对应的
差值累加起来,表示两个采样的距离。所以 discrete learning 的本质是求解一个线性规划问题,其因变量为预估的分布,求解这个分布使得输入的采样和根据分布预估的采样的距离最小。当然,这个变量(即预估的分布)需要满足一些基本的约束,比如对应的概率取值不小于 0,以及所有概率值的和为 1。

使用 discrete learning 有一个前提条件:输入的采样必须是在原数据集上通过简单随机采样得来的,即采样过程服从二项分布。在上述提到的不同采样策略中,

可能并不是一个简单随机采样,所以需要对
预处理构造出一个虚拟的采样,该虚拟采样是简单随机采样,用作 discrete learning 的输入。

各种采样策略

上面提到,针对不同的数据分布,使用不同的采样策略效果会不同,即不同的 p, q 和 u 的取值策略。论文列举出了 10 种不同的 CSDL 变种,对应 10 种不同的采样策略。在这 10 种变种中,对同一个 join key 值 v,

都是相等的(论文的说法是为了避免采样集合太大超过预期,个人理解这里应该是为了简化问题缩小讨论空间)。这 10 个变种可以被划分为 4 类:
  1. 对于所有的 join key 值,使用相同的 p 值和相同的 q 值;
  2. 对不同的 join key 值 v,
    不同,但 q 使用同一个值;
  3. 对于所有的 join key 值,使用相同的 p 值,但使用不同的 q 值,即
    对各个 v 可能不同;
  4. 对不同的 join key 值 v,
    都不相同;

由于 p 和 q 的取值范围是 [θ, 1],在讨论时考虑三种可能的取值,θ, 1 和 sqrt(θ),即上下界和一个中间的值。这三种取值和四种类型组合起来就形成了 10 种变种。接下来我们按类别分析上述这四类变种所使用的估算方法。

策略 1

对所有的 join key 值 v,q 的取值相同,所以

就是 S 上的一个简单随机采样。将
作为 discrete learning 算法的输入,可以得到一个 join key 值 v 与其相应的在 A 中分布概率的映射,将这个对应的概率记作
,估算出来的 join 结果行数为:

40bdcc53d838d5b86b1568728e3b0461.png

其中,N’ 表示 A 表中所有满足 join key 值在

中的记录的总数,这个值是在线下阶段构造
过程中计算并保留的;
表示
中所有 join key 值的交集。

策略 2

虽然对不同的 join key 值 v,

不同,但 q 使用的是同一个值,所以
依然是 S 上的简单随机抽样,因此可以使用和策略 1 完全相同的公式作为估算方法。在给不同的 v 取不同的 p 值时,论文用到了上面提到过的启发式规则:
正比于 sqrt(
*
)。

策略 3

由于对不同的 join key 值 v,q 的取值不同,

不是 A 上的简单随机抽样,无法直接作为 discrete learning 的输入。通过调整
中 join key 值 v 出现的频次,论文构造出了一个新的虚拟采样
,调整频次的方法为:

b51d0ceecf34b042f84aa04f0104a035.png

由于对所有的 v,q 值是相同且已知的,而采样大小的上限 θ 是给定的,因此 q 值可以被唯一确定出来的。调整后的采样

可以看作是 A 上的简单随机抽样,作为输入应用 discrete learning 后可以估算出 v 值在 A 中分布的概率
,论文说可以将这个
带入策略 1 中的公式计算出 join 结果行数,但个人理解这里应该需要将
乘以 (
/ q) 的结果作为策略 1 中的
,而不是直接用
带入。

策略 4

这种情形和策略 3 本质上是一样的,也就是说,p 值对于 v 是否可变并不重要,真正有影响的是 q 值对于 v 是否可变,因为它决定了

是否是简单随机采样,是否可以直接用作 discrete learning 的输入。

论文对策略 ½ 和策略 ¾ 做了简单的对比讨论,提出了一个问题:为什么不直接用策略 ½ 采样,而要考虑策略 ¾?很明显,前者更简单,不需要构造虚拟采样这一步,但后者可以给那些在 A 中出现频次更高的 v 赋予更大的

值,让这些 v 值在采样中占比更高,而它们为 join 结果集贡献也往往更高,所以通过给不同 v 赋予不同
值,可以降低不同估算的准确度的方差。因此从理论上说,策略 ¾ 会比 策略 ½ 表现更好。

哪种策略最好?

上面理论分析认为策略 ¾ 会比策略 ½ 更好,那么在实验中,究竟哪一个具体的变种才是表现最好的呢?论文在 Join Order Benchmark 上做了一些验证,发现了属于策略 3 的两个变种表现最好:

  • CSDL(1, diff):p 值对所有 v 都取 1,q 和 u 对不同的 v 取不同的值;
  • CSDL(θ, diff):p 值对所有 v 都取 θ,q 和 u 对不同的 v 取不同的值;

这两个变种在不同的数据分布下各有胜负,论文将影响结果的数据分布特点总结成了一个指标 join value density,其定义如下:

74f45fd4722331b01d0d432cf98e0555.png

当 jvd 较小时,CSDL(1, diff) 表现更好;当 jvd 较大时,CSDL(θ, diff) 表现更好。这个结论从直观上很好理解,jvd 越小表明 A 表和 B 表在 join key 上值的分布越集中,因此采样时最好能将所有的 join key 值都采进 V 里,不然漏掉任何一个 join key 值可能就意味着在 join 估算中漏掉了大量的记录,所以 p 值应该取 1;相反,当 jvd 较大时,A 表和 B 表在 join key 上值的分布越分散,这时候采样中漏掉一些 join key 值影响不算大,可以将更多的采样空间留给 q 和 u,毕竟这两个参数离真实的 join 结果会更“近”一些。

论文将这两个变种结合起来,取名为 CSDL-opt。

考虑过滤条件

上述的讨论都是针对的两表等值连接,且不带过滤条件的情形,对于更一般的等值连接情形,比如像开篇给出的那个查询用例,CSDL 是怎么应用的呢?

对于线下阶段的抽样,没有任何变化,因为过滤条件一般只有在线上查询运行时才能知道具体是什么。在线上估算阶段,首先对

应用过滤条件,得到过滤后的采样
,然后估算 join 的结果行数为:

f85ed91013e3c0d76438afddc8797959.png

其中,

表示
中所有 join key 值的交集,N’’ 表示 A 表中所有满足 join key 值在
中的记录的总数,而
表示 v 值对应的 sentry 是否满足过滤条件,它们的值要么为 0,要么为 1。

总结

这篇论文主要的亮点在于:

  • 用一个模型描述了关联采样这个领域的所有方法;
  • 利用这个模型发现了一种新的关联采样方法 CSDL
    • 利用 discrete learning 作为估算方法,而不是常用的 scaling up,前者可以在小的采样集合上有很好的估算结果;
    • 总结了 jvd 这个数据分布特点,在不同数据分布下找出了更好的采样策略,总结成了 CSDL-opt 方法;

参考文献

[1] G. Valiant and P. Valiant. Instance optimal learning of discrete distributions. In STOC, pages 142–155. ACM, 2016.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值