在事实表与维表的关联查问时,经常会遇到须要对维表的数据进行过滤或者针对维表做计算的状况,这时能够有两种解决形式:
1、先做关联(如果是内存则能够是预关联),再对关联后的事实表进行过滤。就象在《性能优化技巧:预关联》和《性能优化技巧:外键序号化》中做的那样。
2、先对维表进行过滤,再与事实表做关联。咱们晓得,建设关联时须要维表有索引,过滤之后,原先的索引不再可用了,须要重建索引来产生新的索引。
这两种形式孰优孰劣,不能一概而论,该当和维表与事实表的数据规模比照无关。上面咱们通过试验来探讨一下这些性能优化技巧的成果。
一、测试环境
采纳 TPCH 规范生成的 8 张数据表,共 50G 数据。TPCH 数据表的构造网上有很多介绍,这里就不再赘述了。
测试机有两个 Intel2670 CPU,主频 2.6G,共 16 核,内存 128G,SSD 固态硬盘。
为不便看出差距,上面测试都用单线程计算,多核不起作用。
二、数据表全内存
所谓全内存,就是事后把要用到的数据表全都加载到内存里。咱们抉择 customer 作为维表,共 750 万条记录;用 orders 作为事实表,共 7500 万条记录。
查问时对维表的过滤条件是 left(C_NAME,4)!=”shen” && C_NATIONKEY>-1 && C_ACCTBAL>bal,求满足这些条件的订单总价。其中前两个条件总是为真(为了减少维表过滤的计算量,以加强试验的比照成果),bal 是个参数,用来测试维表过滤后不同数据规模下的成果。
1. 预关联
咱们先看预关联后的状况,编写 SPL 脚本如下:
A1 中读入维表并创立索引,A2 中读入事实表,A3 中进行预关联,这些工夫都不计入测试工夫,从 A4 才开始计时。
2. 重建索引
编写 SPL 脚本如下:
A4 中 customer 过滤后再重建索引,A5 中进行关联。
3. 复用索引
SPL 反对在过滤后复用已有的索引,只需将上述 A4 单元格脚本改为:
=customer.select@i(left(C_NAME,4)!=”shen” && C_NATIONKEY>-1 && C_ACCTBAL>bal)
select 加选项 @i 示意复用 customer 原来的索引。
4. 外键序号化
预加载数据表时加载序号化解决过的组表 customer_xh.ctx 和 orders_xh.ctx。
编写 SPL 脚本如下:
序号化关联不须要索引,所以 A1 中不创立索引。A4 中用 customer:# 示意用 O_CUSTKEY 的值与 customer 的行号关联。
5. 序号化后对位序列
预加载数据表时加载序号化解决过的组表 customer_xh.ctx 和 orders_xh.ctx。
编写 SPL 脚本如下:
在 A4 中用 customer.(过滤条件) 算出一个与记录数等长的、值为 true 或 false 的序列,咱们称之为对位序列;orders 表中的 O_CUSTKEY 曾经序号化解决过,它的值对应于 customer 的记录行号,所以在 A5 就能够用 A4(O_CUSTKEY)来判断 orders 中此行数据是否满足过滤条件。
6. 测试后果与剖析
试验取得测试后果如下(单位:秒):
这个试验中,维表数据记录 750 万行,事实表 orders 数据记录 7500 万行,是维表的 10 倍。
在预关联和外键序号化测试中,采纳的是先关联后再过滤的解决形式,简单的过滤计算要在事实表的行上进行,也就是说过滤计算量是间接过滤维表的 10 倍!所以整个查问的运行工夫是最长的。预关联与外键序号化相比,在查问时,前者会省去关联这一步,所以比后者速度快。
在重建索引和复用索引测试中,采纳的是先对维表过滤后再与事实表关联的解决形式,简单的过滤计算只在维表的行上进行,所以比预关联和外键序号化要快。复用索引与重建索引相比,过滤、关联、求和的计算量雷同,但会在创立索引这一步上节约工夫,所以查问速度也更快。随着维表过滤后的数据规模越来越小,重建索引的工夫也会缩小,整体差距就会变小。
在对位序列测试中,过滤计算也是只在维表的行上进行,计算出对位序列后,只对事实表进行一次过滤,而不必与事实表关联,不必建索引也不必计算 hash 值,所以速度是最快的!
三、维表内存、事实表外存
这次咱们抉择 orders 作为维表,共 7500 万条记录;用 lineitem 作为事实表,共 3 亿条记录。
查问时对维表的过滤条件是 left(O_ORDERPRIORITY,2)!=”9-” && O_ORDERSTATUS!=”A” && O_ORDERDATE>date(“1990-01-01”) && O_TOTALPRICE>price,求满足这些条件的订单总价。其中前三个条件总是为真(为了减少维表过滤的计算量,以加强试验的比照成果),price 是个参数,用来测试维表过滤后不同数据规模下的成果。
1. 关联后再过滤
咱们先看关联后再过滤的状况,编写 SPL 脚本如下:
A1 中读入维表并创立索引,这不计入测试工夫,从 A2 才开始计时。
因为事实表很大,应用游标读取数据,并与维表关联后再过滤。
2. 重建索引
编写 SPL 脚本如下:
A3 中 orders 过滤后再重建索引。
3. 复用索引
只需将上述 A3 单元格脚本改为:
=orders.select@i(left(O_ORDERPRIORITY,2)!=”9-” && O_ORDERSTATUS!=”A” && O_ORDERDATE>date(“1990-01-01”) && O_TOTALPRICE>price)
select 加选项 @i 示意复用 orders 原来的索引。
4. 外键序号化
预加载数据表时加载序号化解决过的组表 orders_xh.ctx,且不必创立索引。
编写 SPL 脚本如下:
A4 中用 orders:# 示意用 L_ORDERKEY 的值与 orders 的行号关联。
5. 序号化后对位序列
预加载数据表时加载序号化解决过的组表 orders_xh.ctx,且不必创立索引。
编写 SPL 脚本如下:
查问实现原理与全内存时雷同。
6. 测试后果与剖析
试验取得测试后果如下(单位:秒):
这个试验中,维表数据记录 7500 万行,事实表 lineitem 数据记录 3 亿行,是维表的 4 倍。
查问过程的计算原理与上一节剖析的雷同,但事实表与维表的数据规模比照倍数降落,由 10 倍变为了 4 倍,外键序号化与复用索引相比,速度差距不是很显著了,甚至在维表过滤掉的记录较少时,因为序号化关联比 hash 值比对关联更占优势,查问速度还略快。
四、总结
依据后面的测试后果和剖析,对于维表有过滤或计算时的查问,应该采纳何种优化技巧来获得最佳性能,咱们作如下总结。
1、事实表数据记录比维表小
1) 如果数据表可能全副装进内存,采纳预关联。
2) 如果不能装进内存,但对维表和外键做了序号化解决,采纳先序号化关联再对事实表过滤。
3) 如果不能装进内存,又没有做序号化解决,采纳先按外键值关联再对事实表过滤。
2、事实表数据记录远大于维表
1) 如果数据表做了序号化解决,采纳对位序列技术。
2) 如果数据表没做序号化解决,采纳先对维表过滤并复用索引,再按外键值关联查问。
3、事实表数据记录比维表大得不多
1) 如果数据表做了序号化解决,采纳对位序列技术。
2) 如果数据表没做序号化解决,采纳预关联 (能装进内存的状况下) 还是复用索引,倡议最好是实测一下。