性能優化技巧:外鍵序號化

一、  問題背景與適用場景

在《性能優化技巧:部分預關聯》一文中,我們介紹了將維表內存化並預關聯的技術,但事實表與維表關聯時,仍需進行hash計算和比對,怎麼提高這一步的性能呢?我們今天再介紹一種優化技巧:外鍵序號化。

外鍵序號化的思路是,如果維表的主鍵是從1開始的自然數(也就是記錄所在行號),那麼就可以用鍵值直接按行號定位維表記錄,而不再需要計算和比對HASH值了,從而加快與維表關聯的速度,進一步提升性能。而且,直接用序號定位,還不需要建立索引,佔用內存也會小很多。

我們下面來介紹如何在SPL中使用外鍵序號化技巧,並使用上文的測試環境,針對同一個查詢問題,以序號化後的數據與之前的數據做對照實驗,驗證序號化的性能提升效果。

 

二、  序號化準備

要使用外鍵序號化技巧,必須要保證維表的主鍵值正好是序號(記錄行號),而實際業務中維表的主鍵值往往不是這樣,所以要先將維表的主鍵轉換成序號。轉換的方法如下:

1)新建一個鍵值-序號對應表,保存維表的鍵值和自然序號的對應關係;

2)把維表的鍵值替換爲自然序號,得到一個新的維表文件;

3)把事實表裏的外鍵值修改爲序號,修改的依據是鍵值-序號對應表,修改後得到一個新的事實表。

本次實驗要用到的三張維表分別是supplier、part與orders,事實表是lineitem,下面分別對它們實現序號化。

1.  supplier序號化

實現序號化的SPL腳本如下:

bef4400cbc05de35bf684369d9db10ed.gif A
1 =file("/home/tbl/supplier.tbl").cursor(;   , "|").new(_1:S_SUPPKEY, _2:S_NAME, _3:S_ADDRESS, _4:S_NATIONKEY,   _5:S_PHONE, _6:S_ACCTBAL).fetch().derive(#:xh)
2 =file("/home/btx/supplier_xh_key.btx").export@b(A1,S_SUPPKEY,xh)
3 =A1.new(xh:S_SUPPKEY,   S_NAME, S_ADDRESS, S_NATIONKEY, S_PHONE, S_ACCTBAL)
4 =file("/home/ctx/supplier_xh.ctx").create(#S_SUPPKEY,   S_NAME, S_ADDRESS, S_NATIONKEY, S_PHONE, S_ACCTBAL)
5 >A4.append(A3.cursor())

A1   從原始數據文件supplier.tbl中讀出數據,並用derive函數新增加一列xh,用行號作爲字段值

A2   將A1中的S_SUPPKEY、xh兩字段輸出到集文件supplier_xh_key.btx中,生成鍵值與序號對應關係表,以備序號化事實表時使用

A3   以xh字段值代替S_SUPPKEY字段,重構supplier序表

A4   創建序號化後的組表文件supplier_xh.ctx

A5   將重構後的supplier序表保存到組表文件supplier_xh.ctx中

2.  part序號化

實現序號化的SPL腳本如下:

bef4400cbc05de35bf684369d9db10ed.gif A
1 =file("/home/tbl/part.tbl").cursor(;   , "|").new(_1:P_PARTKEY, _2:P_NAME, _3:P_MFGR, _4:P_BRAND,   _5:P_TYPE, _6:P_SIZE, _7:P_CONTAINER, _8:P_RETAILPRICE).fetch().derive(#:xh)
2 =file("/home/btx/part_xh_key.btx").export@b(A1,P_PARTKEY,xh)
3 =A1.new(xh:P_PARTKEY,   P_NAME,P_MFGR, P_BRAND, P_TYPE, P_SIZE, P_CONTAINER, P_RETAILPRICE)
4 =file("/home/ctx/part_xh.ctx").create(  #P_PARTKEY, P_NAME,P_MFGR, P_BRAND, P_TYPE,   P_SIZE, P_CONTAINER, P_RETAILPRICE)
5 >A4.append(A3.cursor())

腳本原理與supplier表序號化相同,生成的鍵值與序號對應關係表爲part_xh_key.btx,序號化後的組表文件叫part_xh.ctx。

3.  orders序號化

實現序號化的SPL腳本如下:

bef4400cbc05de35bf684369d9db10ed.gif A
1 =file("/home/tbl/orders.tbl").cursor(;   , "|").new(_1:O_ORDERKEY, _2:O_CUSTKEY,   _3:O_ORDERSTATUS,_4:O_TOTALPRICE,    _5:O_ORDERDATE,   _6:O_ORDERPRIORITY,_7:O_SHIPPRIORITY).fetch().derive(#:xh)
2 =file("/home/btx/orders_xh_key.btx").export@b(A1,O_ORDERKEY,xh)
3 =A1.new(xh:O_ORDERKEY,O_CUSTKEY,O_ORDERSTATUS,O_TOTALPRICE,  O_ORDERDATE,O_ORDERPRIORITY,O_SHIPPRIORITY)
4 =file("/home/ctx/orders_xh.ctx").create(    #O_ORDERKEY,O_CUSTKEY,O_ORDERSTATUS,O_TOTALPRICE,  O_ORDERDATE,O_ORDERPRIORITY,O_SHIPPRIORITY)  
5 >A4.append(A3.cursor())

腳本原理與supplier表序號化相同,生成的鍵值與序號對應關係表爲orders_xh_key.btx,序號化後的組表文件叫orders_xh.ctx。

4.  lineitem序號化

實現序號化的SPL腳本如下:

bef4400cbc05de35bf684369d9db10ed.gif A
1 =file("/home/tbl/lineitem.tbl").cursor(;   , "|").new(  _1:L_ORDERKEY,   _4:L_LINENUMBER, _2:L_PARTKEY, _3:L_SUPPKEY,    _5:L_QUANTITY, _6:L_EXTENDEDPRICE,_7:L_DISCOUNT, _8:L_TAX, _9:L_RETURNFLAG,   _10:L_LINESTATUS,_11:L_SHIPDATE,     _12:L_COMMITDATE, _13:L_RECEIPTDATE,_14:L_SHIPINSTRUCT,  _15:L_SHIPMODE, _16:L_COMMENT)
2 =file("/home/btx/orders_xh_key.btx").import@b()
3 =file("/home/btx/part_xh_key.btx").import@b()
4 =file("/home/btx/supplier_xh_key.btx").import@b()
5 =A1.switch(L_ORDERKEY,A2:O_ORDERKEY;L_PARTKEY,A3:P_PARTKEY;L_SUPPKEY,A4:S_SUPPKEY)
6 =A5.run(L_ORDERKEY=L_ORDERKEY.xh,   L_PARTKEY=L_PARTKEY.xh, L_SUPPKEY=L_SUPPKEY.xh)
7 =file("/home/ctx/lineitem_xh.ctx").create(#L_ORDERKEY,#L_LINENUMBER,L_PARTKEY,   L_SUPPKEY,  L_QUANTITY,   L_EXTENDEDPRICE,L_DISCOUNT, L_TAX,    L_RETURNFLAG, L_LINESTATUS, L_SHIPDATE, L_COMMITDATE,  L_RECEIPTDATE,L_SHIPINSTRUCT, L_SHIPMODE,   L_COMMENT;L_ORDERKEY)
8 >A7.append(A6)

A1   創建讀入lineitem原始數據的遊標

A2/A3/A4   分別讀入orders、part、supplier鍵值與序號對應關係表

A5   用L_ORDERKEY與orders對應關係表關聯,用L_PARTKEY與part對應關係表關聯,用L_SUPPKEY與supplier對應關係表關聯

A6   用關聯後的序號值替換鍵值生成新的遊標

A7   創建序號化後的組表文件lineitem_xh.ctx

A8   將序號化後的遊標數據寫入組表lineitem_xh.ctx

 

三、  序號化測試

1.   原始數據測試

維表預加載SPL腳本如下:

bef4400cbc05de35bf684369d9db10ed.gif A
1 >env(supplier, file("/home/ctx/supplier.ctx").create().memory().keys@i(S_SUPPKEY))
2 >env(part, file("/home/ctx/part.ctx").create().memory().keys@i(P_PARTKEY))
3 >env(orders,file("/home/ctx/orders.ctx").create().memory().keys@i(O_ORDERKEY))

加載維表並建索引。

 

編寫SPL測試腳本如下:

bef4400cbc05de35bf684369d9db10ed.gif A
1 =file("/home/ctx/lineitem.ctx").create().cursor(L_ORDERKEY,L_PARTKEY,   L_SUPPKEY,L_EXTENDEDPRICE,L_DISCOUNT,L_SHIPDATE)
2 =A1.switch(L_ORDERKEY,orders;L_PARTKEY,part;L_SUPPKEY,supplier)
3 =A2.select(L_ORDERKEY.O_TOTALPRICE>0   && L_PARTKEY.P_SIZE>0 && L_SUPPKEY.S_ACCTBAL<999999)
4 =A3.groups(year(L_SHIPDATE):l_year;   sum(L_EXTENDEDPRICE * (1 - L_DISCOUNT)):revenue)

先運行維表預加載腳本,再運行測試腳本,得到測試腳本運行時間爲450秒。

 

2.  序號化數據測試

維表預加載SPL腳本如下:

bef4400cbc05de35bf684369d9db10ed.gif A
1 >env(supplier, file("/home/ctx/supplier_xh.ctx").create().memory())
2 >env(part, file("/home/ctx/part_xh.ctx").create().memory())
3 >env(orders,file("/home/ctx/orders_xh.ctx").create().memory())

加載的是序號化後的維表,不需要建立索引。

編寫SPL測試腳本如下:

bef4400cbc05de35bf684369d9db10ed.gif A
1 =file("/home/ctx/lineitem_xh.ctx").create().cursor(L_ORDERKEY,L_PARTKEY,   L_SUPPKEY,L_EXTENDEDPRICE,L_DISCOUNT,L_SHIPDATE)
2 =A1.switch(L_ORDERKEY,orders:#;L_PARTKEY,part:#;L_SUPPKEY,supplier:#)
3 =A2.select(L_ORDERKEY.O_TOTALPRICE>0   && L_PARTKEY.P_SIZE>0 && L_SUPPKEY.S_ACCTBAL<999999)
4 =A3.groups(year(L_SHIPDATE):l_year;   sum(L_EXTENDEDPRICE * (1 - L_DISCOUNT)):revenue)

注意:A2中關聯時使用“:#”與維表關聯,表示用事實表中的鍵值與維表的行號進行關聯,假如鍵值是7,則直接與維表的第7行關聯。

先運行維表預加載腳本,再運行測試腳本,得到測試腳本運行時間爲269秒。

 

3.  分析與結論

在上面兩組對照實驗中,序號化後的數據與序號化前相比,維表的記錄數、字段數完全相同,事實表的記錄數與字段數也完全相同,僅有相關的鍵值換成了序號。查詢過程相比,過濾條件完全相同,過濾後的參與計算的數據完全相同,也就是說過濾與分組求和所用的時間完全相同,所不同的僅有關聯的方式(行號關聯、鍵值的hash值比對關聯),而運行時間減少了450-269=181秒,可見,外鍵序號化對性能提升效果十分顯著。

 

四、  進一步說明

序號化的字段必須是維表的主鍵,但不限主鍵字段的數據類型,整數、字符串、日期、時間等等都可以序號化。對於多主鍵維表,可以新增一個序號字段,建立多個鍵值與序號的對應關係表,並依此對事實表進行序號化。

一般來說,外鍵序號化技巧可以很方便地適用於歷史數據的查詢,只需對歷史數據進行一次序號化就可以使用了,鍵值與序號對應關係表也無須再保留。

但外鍵序號化技巧同樣適用於有新增數據的查詢,只是會多增加些步驟。

1.  維表與事實表均有新增數據

1)先取得維表新增加的記錄,追加鍵值與序號對應關係表;

2)再把新增記錄追加到序號化後的維表,追加時依據鍵值與序號對應關係表;

3)再把事實表新增加的記錄追加到序號化後的事實表,追加時依據鍵值與序號對應關係表;

2.  僅事實表有新增數據

在維表數據保持不變的情況下,僅需進行上述第3)步即可。

 

處理好新增數據以後,就可以使用外鍵序號化關聯查詢技巧了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章