Db2 中计算 OR 关系组合列选择率的原理

问题与实例

问题非常简单,Db2 是如何估算如下语句所带谓词条件的选择率的:
SELECT * FROM testset WHERE c1=? or c2=? or c3=? or c4=?;
为了方便说明,我们从一个实际例子入手,在 Db2 中构造如下表,插入 12 条数据,并收集统计信息:

CREATE TABLE testset (c1 INT, c2 INT, c3 INT, c4 INT);
INSERT INTO testset VALUES 
(0,0,0,0),
(1,1,1,1),
(2,2,2,2),
(3,3,3,0),
(4,4,0,1),
(5,5,1,2),
(6,0,2,0),
(7,1,3,1),
(8,2,0,2),
(9,3,1,0),
(10,4,2,1),
(11,5,3,2);
RUNSTATS ON TABLE testset;

用 db2look -d sample -e -t testset -m 看下统计信息:

UPDATE SYSSTAT.COLUMNS
SET COLCARD=12,
    NUMNULLS=0,
    SUB_COUNT=-1,
    SUB_DELIM_LENGTH=-1,
    PCTENCODED=-1,
    AVGCOLLENCHAR=-1,
    PAGEVARIANCERATIO=-1.000000,
    AVGENCODEDCOLLEN=-1.000000,
    HIGH2KEY='10',
    LOW2KEY='1',
    AVGCOLLEN=5
WHERE COLNAME = 'C1' AND TABNAME = 'TESTSET' AND TABSCHEMA = 'DB2INST1';

UPDATE SYSSTAT.COLUMNS
SET COLCARD=6,
    NUMNULLS=0,
    SUB_COUNT=-1,
    SUB_DELIM_LENGTH=-1,
    PCTENCODED=-1,
    AVGCOLLENCHAR=-1,
    PAGEVARIANCERATIO=-1.000000,
    AVGENCODEDCOLLEN=-1.000000,
    HIGH2KEY='4',
    LOW2KEY='1',
    AVGCOLLEN=5
WHERE COLNAME = 'C2' AND TABNAME = 'TESTSET' AND TABSCHEMA = 'DB2INST1';

UPDATE SYSSTAT.COLUMNS
SET COLCARD=4,
    NUMNULLS=0,
    SUB_COUNT=-1,
    SUB_DELIM_LENGTH=-1,
    PCTENCODED=-1,
    AVGCOLLENCHAR=-1,
    PAGEVARIANCERATIO=-1.000000,
    AVGENCODEDCOLLEN=-1.000000,
    HIGH2KEY='2',
    LOW2KEY='1',
    AVGCOLLEN=5
WHERE COLNAME = 'C3' AND TABNAME = 'TESTSET' AND TABSCHEMA = 'DB2INST1';

UPDATE SYSSTAT.COLUMNS
SET COLCARD=3,
    NUMNULLS=0,
    SUB_COUNT=-1,
    SUB_DELIM_LENGTH=-1,
    PCTENCODED=-1,
    AVGCOLLENCHAR=-1,
    PAGEVARIANCERATIO=-1.000000,
    AVGENCODEDCOLLEN=-1.000000,
    AVGCOLLEN=5
WHERE COLNAME = 'C4' AND TABNAME = 'TESTSET' AND TABSCHEMA = 'DB2INST1';

可以看到,表中一共有 12 条数据,收集了统计信息后,Db2 优化器知道了 c1, c2, c3, c4 的 NDV(Number of Distinct Value)分别是 12, 6, 4, 3。
我们考虑如下语句:SELECT * FROM testset WHERE c1=? or c2=? or c3=? or c4=?;
我们先来猜测下 Db2 优化器对这个谓词条件评估的选择率是多少?
最自然的想法,是不是 1 12 + 1 6 + 1 4 + 1 3 = 0.833 \frac{1}{12}+\frac{1}{6}+\frac{1}{4}+\frac{1}{3}=0.833 121+61+41+31=0.833呢?答案并不是,因为这只是简单相加,并不符合 OR 的含义。我们看下 Db2 优化器实际给出的估计:
EXPLAIN ALL FOR SELECT * FROM testset WHERE c1=? or c2=? or c3=? or c4=?
db2exfmt -d sample -1

Predicates:
----------
2) Sargable Predicate, 
	Comparison Operator: 		Not Applicable
	Subquery Input Required: 	No
	Filter Factor: 			0.618056

	Predicate Text:
	--------------
	((((Q1.C1 = ?) OR 
	   (Q1.C2 = ?)) OR 
	  (Q1.C3 = ?)) OR 
	 (Q1.C4 = ?))

这里是 0.618056,下面就解释下这个数字是怎么被计算出来的,可以用两种方法进行解释。

集合包容排斥原理方法

Recall 一下集合包容排斥原理(inclusion-exclusion principle):
A 1 , . . . A n A_1,...A_n A1,...An为有限集合,则:
∣ ⋃ i = 1 n A i ∣ = ∑ i = 1 n ∣ A i ∣ − ∑ 1 ≤ i < j ≤ n ∣ A i ∩ A j ∣ + ∑ 1 ≤ i < j < k ≤ n ∣ A i ∩ A j ∩ A k ∣ − . . . + ( − 1 ) n − 1 ∣ A 1 ∩ . . . ∩ A n ∣ \vert\bigcup_{i=1}^{n}A_i\vert=\sum_{i=1}^{n}\vert A_i\vert-\sum_{1\le i<j\le n}\vert A_i\cap A_j\vert +\sum_{1\le i<j<k\le n}\vert A_i\cap A_j \cap A_k\vert -...+(-1)^{n-1}\vert A_1\cap ...\cap A_n\vert i=1nAi=i=1nAi1i<jnAiAj+1i<j<knAiAjAk...+(1)n1A1...An
对于两个集合来说,所表示的就是:
∣ A 1 ∪ A 2 ∣ = ∣ A 1 ∣ + ∣ A 2 ∣ − ∣ A 1 ∩ A 2 ∣ \vert A_1 \cup A_2\vert =\vert A_1\vert +\vert A_2\vert -\vert A_1\cap A_2\vert A1A2=A1+A2A1A2
对于三个集合则是:
∣ A 1 ∪ A 2 ∪ A 3 ∣ = ∣ A 1 ∣ + ∣ A 2 ∣ + ∣ A 3 ∣ − ∣ A 1 ∩ A 2 ∣ − ∣ A 1 ∩ A 3 ∣ − ∣ A 2 ∩ A 3 ∣ + ∣ A 1 ∩ A 2 ∩ A 3 ∣ \vert A_1 \cup A_2\cup A_3\vert =\vert A_1\vert +\vert A_2\vert +\vert A_3\vert -\vert A_1\cap A_2\vert -\vert A_1\cap A_3\vert -\vert A_2\cap A_3\vert +\vert A_1\cap A_2\cap A_3\vert A1A2A3=A1+A2+A3A1A2A1A3A2A3+A1A2A3
示意图如下:
在这里插入图片描述
首先,选择率(Selectivity)、元素个数(Cardinality)都可以看做是一个集合的某种测度。
其次,对于优化器来说,估计 OR 关系组合列的选择率是比较困难的,而估计 AND 关系组合列的选择率则比较简单,比如可以收集组合列统计信息,也可以使用简单的乘法法则。因此就考虑用多个集合的交集元素个数来计算并集元素个数。
下一步,我们可以将不同的谓词条件看做是一个集合,如下:
A 1 A_1 A1:{ SELECT * FROM testset WHERE c1=?}
A 2 A_2 A2:{ SELECT * FROM testset WHERE c2=?}
A 3 A_3 A3:{ SELECT * FROM testset WHERE c3=?}
A 4 A_4 A4:{ SELECT * FROM testset WHERE c4=?}
A 1 ∪ A 2 ∪ A 3 ∪ A 4 A_1\cup A_2\cup A_3\cup A_4 A1A2A3A4:{ SELECT * FROM testset WHERE c1=? or c2=? or c3=? or c4=?}
同时可以把不同谓词条件的“选择率”看作是集合元素的“个数”,前面说过,这两个都类似于“测度”,得到如下:
∣ A 1 ∣ = 1 12 , ∣ A 2 ∣ = 1 6 , ∣ A 3 ∣ = 1 4 , ∣ A 4 ∣ = 1 3 \vert A_1\vert=\frac{1}{12},\vert A_2\vert=\frac{1}{6},\vert A_3\vert=\frac{1}{4},\vert A_4\vert=\frac{1}{3} A1=121,A2=61,A3=41,A4=31
∣ A 1 ∩ A 2 ∣ = 1 72 , ∣ A 1 ∩ A 3 ∣ = 1 48 , ∣ A 1 ∩ A 4 ∣ = 1 36 \vert A_1\cap A_2\vert=\frac{1}{72},\vert A_1\cap A_3\vert=\frac{1}{48},\vert A_1\cap A_4\vert=\frac{1}{36} A1A2=721,A1A3=481,A1A4=361
∣ A 2 ∩ A 3 ∣ = 1 24 , ∣ A 2 ∩ A 4 ∣ = 1 18 , ∣ A 3 ∩ A 4 ∣ = 1 12 \vert A_2\cap A_3\vert=\frac{1}{24},\vert A_2\cap A_4\vert=\frac{1}{18},\vert A_3\cap A_4\vert=\frac{1}{12} A2A3=241,A2A4=181,A3A4=121
∣ A 1 ∩ A 2 ∩ A 3 ∣ = 1 288 , ∣ A 1 ∩ A 2 ∩ A 4 ∣ = 1 216 , ∣ A 1 ∩ A 3 ∩ A 4 ∣ = 1 144 , ∣ A 2 ∩ A 3 ∩ A 4 ∣ = 1 72 \vert A_1\cap A_2\cap A_3\vert=\frac{1}{288},\vert A_1\cap A_2\cap A_4\vert=\frac{1}{216},\vert A_1\cap A_3\cap A_4\vert=\frac{1}{144},\vert A_2\cap A_3\cap A_4\vert=\frac{1}{72} A1A2A3=2881,A1A2A4=2161,A1A3A4=1441,A2A3A4=721
∣ A 1 ∩ A 2 ∩ A 3 ∩ A 4 ∣ = 1 864 \vert A_1\cap A_2\cap A_3\cap A_4\vert=\frac{1}{864} A1A2A3A4=8641
代入公式,可得:
∣ A 1 ∪ A 2 ∪ A 3 ∪ A 4 ∣ \vert A_1\cup A_2\cup A_3\cup A_4\vert A1A2A3A4
= 1 12 + 1 6 + 1 4 + 1 3 − 1 72 − 1 48 − 1 36 − 1 24 − 1 18 − 1 12 + 1 288 + 1 216 + 1 144 + 1 72 − 1 864 =\frac{1}{12}+\frac{1}{6}+\frac{1}{4}+\frac{1}{3}-\frac{1}{72}-\frac{1}{48}-\frac{1}{36}-\frac{1}{24}-\frac{1}{18}-\frac{1}{12}+\frac{1}{288}+\frac{1}{216}+\frac{1}{144}+\frac{1}{72}-\frac{1}{864} =121+61+41+31721481361241181121+2881+2161+1441+7218641
= 534 864 =\frac{534}{864} =864534
= 0.618055555555556 =0.618055555555556 =0.618055555555556
可以看到,和 Db2 优化器估算的一模一样,分毫不差。

概率方法

概率本质上也是一种测度,而用概率的方法比较简单,也非常易于理解。我们可以想象:
集合 A A A:{ SELECT * FROM testset WHERE c1=? or c2=? or c3=? or c4=?}
它的补集 A ˉ \bar{A} Aˉ:{ SELECT * FROM testset WHERE c1<>? and c2<>? and c3<>? and c4<>?}
A ˉ \bar{A} Aˉ的选择率计算是非常简单的,也就是
∣ A ˉ ∣ = ( 1 − 1 12 ) × ( 1 − 1 6 ) × ( 1 − 1 4 ) × ( 1 − 1 3 ) = 330 864 \vert \bar{A}\vert=(1-\frac{1}{12})\times(1-\frac{1}{6})\times(1-\frac{1}{4})\times(1-\frac{1}{3})=\frac{330}{864} Aˉ=(1121)×(161)×(141)×(131)=864330
因此: ∣ A ∣ = 1 − ∣ A ˉ ∣ = 534 864 = 0.618055555555556 \vert A\vert=1-\vert \bar{A}\vert=\frac{534}{864}=0.618055555555556 A=1Aˉ=864534=0.618055555555556
结果也是一样的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朱峥嵘(朱髯)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值