多維分析後臺實踐 3:維度排序壓縮

實踐目標

本期目標,是在完成數據類型轉化基礎上,實現維度排序壓縮,進一步提升計算速度。

實踐的步驟:

1、 準備基礎寬表:修改上期的代碼,完成維度排序壓縮存成新組表。

2、 訪問基礎寬表:上期代碼不必修改,直接應用於新組表。

3、 新增數據追加:每日新增業務數據追加,每月重新排序重整。要儘可能不影響訪問基礎寬表的性能,同時減小每日新增數據所需要的時間。

 

本期樣例寬表不變,依然爲 customer 表。從 Oracle 數據庫中取出寬表數據的 SQL 語句是 select * from customer。執行結果如下圖:

 ..

 

假設當天日期是 2021-01-12,則取出當日新增數據的 SQL 是:

select * from customer where begin_date=to_date('2021-01-12','yyyy-mm-dd')

 

多維分析計算的目標也不變,用下面 Oracle 的 SQL 語句表示:

select department_id,job_id,to_char(begin_date,'yyyymm') begin_month ,sum(balance) sum,count(customer_id) count

from customer

where department_id in (10,20,50,60,70,80)

and job_id in ('AD_VP','FI_MGR','AC_MGR','SA_MAN','SA_REP')

and begin_date>=to_date('2002-01-01','yyyy-mm-dd')

and begin_date<=to_date('2020-12-31','yyyy-mm-dd')

and flag1='1' and flag8='1'

group by department_id,job_id,to_char(begin_date,'yyyymm')

 

準備寬表

維度排序壓縮:有序列存。列存是指列式存儲,集算器新建組表時,默認列存。

有序是指字段值物理有序存儲,也就是用維度字段排序後存入組表。用於排序的維度字段順序非常關鍵,要將重複度高的維度排在前面。

本例的維度包括:department_id,job_num,employee_id,begin_date,customer_id。其中,部門編號 department_id 總數最少(事實表中只出現 11 個部門),所以重複度最高。其他字段中,job_num,employee_id,begin_date,customer_id 重複度依次降低。

同時,考慮實際應用中,分組字段出現的情況也和重複度基本一致,所以排序的字段順序可以確定爲:department_id,job_num,employee_id,begin_date,customer_id。

我們用數據庫來做排序。示例如下:

select department_id,job_id,employee_id,begin_date,customer_id,first_name,last_name,phone_number,job_title,balance,department_name,flag1,flag2,flag3,flag4,flag5,flag6,flag7,flag8

from customer order by department_id,job_id,employee_id,begin_date,customer_id。

執行結果如圖:

..

 

根據以上要求改寫 etl.dfx,從數據庫中取出排序數據,類型轉化後,生成組表文件,存儲基礎寬表。代碼示例如下:

bef4400cbc05de35bf684369d9db10ed.gif A B
1 =connect@l("oracle")
2 =A1.cursor@d("select   department_id,job_id,employee_id,begin_date,customer_id,first_name,last_name,phone_number,job_title,balance,department_name,flag1,flag2,flag3,flag4,flag5,flag6,flag7,flag8   from customer order by department_id,job_id,employee_id,begin_date,customer_id")
3 =A1.query@d("select   job_id from jobs order by job_id") =file("data/job.btx").export@z(A3)  
4 =A3.(job_id) =date("2000-01-01")
5 =A2.new(int(department_id):department_id,A4.pos@b(job_id):job_num,int(employee_id):employee_id,int(interval@m(B4,begin_date)*100+day(begin_date)):begin_date,int(customer_id):customer_id,first_name,last_name,phone_number,job_title,float(balance):balance,department_name,int(flag1):flag1,int(flag2):flag2,int(flag3):flag3,int(flag4):flag4,int(flag5):flag5,int(flag6):flag6,int(flag7):flag7,int(flag8):flag8)
6 =file("data/customer.ctx").create@y(#department_id,#job_num,#employee_id,#begin_date,#customer_id,first_name,last_name,phone_number,job_title,balance,department_name,flag1,flag2,flag3,flag4,flag5,flag6,flag7,flag8)
7 =A6.append(A5) >A6.close(),A1.close()

其中:A2 的 SQL 語句增加了排序,A6 的組表指定了排序字段。

其他代碼和上期一致。

 

數據量爲一億,導出組表文件和前幾期的組表文件比較如下:

期數 文件大小 說明 備註
第一期 3.5GB 直接從數據庫導出,未做優化
第二期 3.0GB 完成數據類型優化
第三期 2.4GB 完成前面的優化和維度排序壓縮

從上表可以看出,完成數據類型優化之後,文件大小減少了14%(0.5GB)。再完成維度排序壓縮後,又減少了 20%(0.6GB), 總體減少 31%(1.1GB)。文件變小,能減少磁盤讀取數據量,有效提高性能。

訪問寬表

訪問寬表的 SPL 代碼、Java 代碼和上期相比沒有變化。

Java 代碼加上後臺計算返回結果總的執行時間,和前期比較如下:

期數 單線程 二線程並行 備註
第一期 120秒 75秒
第二期 59 秒 36 秒
第三期 21秒 15秒

通過上表的對比可以看出,維度排序壓縮進一步提高了計算性能。

新增數據

客戶表每天都會有新增數據,需要每天定時添加到組表文件中。如果是按日期有序的組表文件,將每天產生的新數據追加到文件的最後即可。但是我們的客戶組表是按照部門等字段有序的,如果在結尾直接追加數據,就不是整體有序了。如果每天都將原有數據和新數據一起重新排序,計算的時間會比較長。

我們可以從數據庫中讀取新數據並按照部門等字段排序,再用 T.append@a() 函數追加,集算器會自動新建一個補文件,每天新數據都有序歸併到補文件中,補文件相對較小,有序歸併耗時較短。每月只需對客戶表文件和補文件重整一次,將補文件有序歸併到組表文件中。

 

採用這個方法,編寫 etlAppend.dfx,網格參數如下:

..

SPL 代碼如下:

bef4400cbc05de35bf684369d9db10ed.gif A B
1 if day(today)==1 =file("data/customer.ctx").reset()
2 =connect@l("oracle")
3 =A2.cursor@d("select   department_id,job_id,employee_id,begin_date,customer_id,first_name,last_name,phone_number,job_title,balance,department_name,flag1,flag2,flag3,flag4,flag5,flag6,flag7,flag8   from customer where begin_date=? order by department_id,job_id,employee_id,begin_date  ",today)
4 =A2.query@d("select   job_id from jobs order by job_id")
5 =A4.(job_id) =date("2000-01-01")
6 =A3.new(int(department_id):department_id,A5.pos@b(job_id):job_num,int(employee_id):employee_id,int(interval@m(B5,begin_date)*100+day(begin_date)):begin_date,int(customer_id):customer_id,first_name,last_name,phone_number,job_title,float(balance):balance,department_name,int(flag1):flag1,int(flag2):flag2,int(flag3):flag3,int(flag4):flag4,int(flag5):flag5,int(flag6):flag6,int(flag7):flag7,int(flag8):flag8)
7 =file("data/customer.ctx").open().append@a(A6)
8 >A7.close(),A2.close()

A1:判斷輸入日期是否是每月第一天,如果是,就執行 B1 對客戶組表進行重整,將新數據形成的補文件有序歸併進入客戶組表文件。

A2:連接 oracle 數據庫。

A3:取出當天數據。

A4:取出 jobs 表數據,用於類型轉換。

A5、B5、A6 與上期 etl.dfx 相同。

A7:將今天新增數據有序歸併到補文件中。

A8:關閉文件和數據庫連接。

 

etlAppend.dfx 需要每天定時執行。執行的方法是用 ETL 工具或者操作系統定時任務,通過命令行調用集算器腳本。

例如:

C:\Program Files\raqsoft\esProc\bin>esprocx d:\olap\etlAppend.dfx


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