性能优化技巧:部分预关联

一、  问题背景与适用场景在《性能优化技巧:预关联》中,我们测试了将数据表事先全部加载进内存并做好关联后的查询性能优化问题,但如果内存不够大,不能将维表和事实表全部装入,那怎么办呢?此时,可以将维表预先装入内存,建好索引,实现维表部分的预关联,省去一半hash计算。我们下面再来测试一下这种场景,这次用数据量最大、内存装不下的lineitem表做测试,在SPL部分预关联中,将其它7张表预先装进内存,而lineitem在查询时才实时读入。二、  SQL测试依然用 Oracle 数据库作为 SQL 测试的代表,从lineitem表里查询每年零件订单的总收入。1.  两表关联查询的SQL语句如下:selectl_year,sum(volume) as revenuefrom(selectextract(year from l_shipdate) as l_year,(l_extendedprice * (1 - l_discount) ) as volumefromlineitem,partwherep_partkey = l_partkeyand length(p_type)>2) shippinggroup byl_yearorder byl_year;2.   六表关联查询的SQL语句如下:selectl_year,sum(volume) as revenuefrom(selectextract(year from l_shipdate) as l_year,(l_extendedprice * (1 - l_discount) ) as volumefromsupplier,lineitem,orders,customer,part,nation n1,nation n2wheres_suppkey = l_suppkeyand p_partkey = l_partkeyand o_orderkey = l_orderkeyand c_custkey = o_custkeyand s_nationkey = n1.n_nationkeyand c_nationkey = n2.n_nationkeyand length(p_type) > 2and n1.n_name is not nulland n2.n_name is not nulland s_suppkey > 0) shippinggroup byl_yearorder byl_year;3.   测试结果两表关联六表关联运行时间(秒)2352669这两个测试数据依然是多次运行后取最快的那次。从测试结果可以看出,六表关联比两表关联慢了2669/235=11.4倍!性能下降非常多。三、  SPL部分预关联测试1.  部分预关联实现预关联的SPL脚本如下:

A1>env(region,   file(path+"region.ctx").create().memory().keys@i(R_REGIONKEY))2>env(nation,   file(path+"nation.ctx").create().memory().keys@i(N_NATIONKEY))3>env(supplier,   file(path+"supplier.ctx").create().memory().keys@i(S_SUPPKEY))4>env(customer,   file(path+"customer.ctx").create().memory().keys@i(C_CUSTKEY))5>env(part,   file(path+"part.ctx").create().memory().keys@i(P_PARTKEY))6>env(orders,file(path+"orders.ctx").create().memory().keys@i(O_ORDERKEY))7>nation.switch(N_REGIONKEY,region)8>customer.switch(C_NATIONKEY,nation)9>supplier.switch(S_NATIONKEY,nation)10>orders.switch(O_CUSTKEY,customer)脚本中前6行分别将6个维表读入内存,生成内表,并建好索引,再设成全局变量。后4行完成维表间连接。在SPL服务器启动时,就先运行此脚本,完成环境准备。2.  两表关联编写SPL脚本如下:

A1=file("/home/btx/lineitem.btx").cursor@tb(L_PARTKEY,L_EXTENDEDPRICE,L_DISCOUNT,L_SHIPDATE)2=A1.switch@i(L_PARTKEY,part).select(len(L_PARTKEY.P_TYPE)>2)3=A2.groups(year(L_SHIPDATE):l_year;   sum(L_EXTENDEDPRICE * (1 - L_DISCOUNT)):revenue)临时装载需要用游标,然后在游标上进行关联,之后的写法和全内存差不多。3.    六表关联编写SPL脚本如下:

A1=file("/home/btx/lineitem.btx").cursor@tb(L_ORDERKEY,L_PARTKEY,L_SUPPKEY,L_EXTENDEDPRICE,L_DISCOUNT,L_SHIPDATE)2=A1.switch@i(L_ORDERKEY,orders;L_PARTKEY,part;L_SUPPKEY,supplier)3=A2.select(len(L_PARTKEY.P_TYPE)>2   && L_ORDERKEY.O_CUSTKEY.C_NATIONKEY.N_NAME!=null &&  L_SUPPKEY.S_NATIONKEY.N_NAME != null   && L_SUPPKEY.S_SUPPKEY>0 )4=A3.groups(year(L_SHIPDATE):l_year;sum(L_EXTENDEDPRICE   * (1 - L_DISCOUNT)):revenue)类似地,建立好游标及关联后的写法和全内存差不多,一样非常简洁易懂。4.   运行结果两表关联六表关联运行时间(秒)266472六表关联仅仅比两表关联慢1.8倍,增加的时间主要用于事实表lineitem中L_ORDERKEY和L_SUPPKEY字段的关联以及增加的过滤条件计算量(引用这些关联表字段)的时间。因为有了部分预关联,维表之间关联运算本身不再消耗时间,而维表与lineitem表关联的时间,也因为事先建好索引而提高了性能(可以减少一半的hash计算)。四、  结论测试结果汇总:运行时间(秒)两表关联六表关联性能降低倍数SQL235266911.4SPL预关联2664721.8六表关联比两表关联,SQL慢了11.4倍,说明SQL处理JOIN消耗CPU很大,性能降低明显。而采用部分预关联机制后的SPL只慢1.8倍,多JOIN几个表影响不大,性能不会明显下降。在进行关联表较多的查询时,如果内存大到足以将除事实表之外的维表数据全部读入内存,使用部分预关联技术依然能有效地提升计算性能!而关系数据库用在关联表很多的时候会发生数据库引擎不会优化的问题,导致性能下降很严重。

(0)

相关推荐

  • connector-x | 让数据从DB高速导入到DataFrame中

    ConnectorX 使您能够以最快和最节省内存的方式将数据从数据库加载到 Python 中. 你需要的是一行代码: import connectorx as cx cx.read_sql(" ...

  • 性能优化技巧:预关联

    一.  问题背景与适用场景SQL中JOIN的性能是个老大难问题,特别是关联表较多时,计算性能会急剧下降.SQL实现JOIN一般是采用HASH分堆的办法,即先计算关联键的HASH值,再将相同HASH值的 ...

  • 性能优化技巧:大事实表与大维表关联

    一.  问题背景与适用场景在<性能优化技巧:小事实表与大维表关联>中,我们尝试了小事实表与大维表关联时的性能优化方法,该方法利用了小事实表可以装入内存的特点,将关联键汇集排序后到大维表中查 ...

  • 性能优化技巧:小事实表与大维表关联

    一.  问题背景与适用场景在主子表关联查询中,有时会遇到这样一种情况:按条件过滤后的事实表数据量很小,能够全部装载进内存或仅比内存略大一点:而要关联的维表数据量很大,比内存要大很多.这种时候,如果维表 ...

  • 性能优化技巧:有序定位关联提速主子关联后的过滤

    一.  问题背景与适用场景在<性能优化技巧:有序归并>中我们验证了有序归并算法提高关联性能的效果,那么还有没有进一步提升的空间呢?能不能再减少数据的读取量从而再提速呢?通常主子关联后还会再 ...

  • 性能优化技巧:维表过滤或计算时的关联

    在事实表与维表的关联查询时,常常会遇到需要对维表的数据进行过滤或者针对维表做计算的情况,这时可以有两种处理方式:1.先做关联(如果是内存则可以是预关联),再对关联后的事实表进行过滤.就象在<性能 ...

  • 揭秘 Vue.js 九个性能优化技巧

    这篇文章主要参考了 Vue.js 核心成员 Guillaume Chau 在 19 年美国的 Vue conf 分享的主题:9 Performance secrets revealed,分享中提到了九 ...

  • 性能优化技巧:前半有序时的排序

    一.  问题背景与适用场景在对数据集进行排序运算时,有时会遇到这样一种场景:数据集T已经按字段a有序,而字段b无序,现在我们要将T按a.b排序,我们称之为前半有序(a有序)的排序.此时我们能想到一种优 ...

  • 性能优化技巧:后半有序分组

    一.  问题背景与适用场景什么是后半有序?如果数据集T已经按字段a.b有序,现在我们要将T按b排序或分组时,因为在a值相同的段内,b都是有序的,这种要排序或分组的字段在分段内有序的情况就称为后半有序. ...

  • 性能优化技巧:有序分组

    一.  问题背景与适用场景通常分组计算都采用hash方案,即先计算分组字段的hash值,hash值相同的记录被分拣到一个小集合里,然后在这个小集合中遍历找分组字段值相同的聚合成一组.分组的复杂度(比较 ...