輕量級可嵌入多維分析後臺

問題的提出

多維分析(BI)系統後臺數據源一般有三種選擇。1、普通數據庫;2、專業數據倉庫;3、BI 系統自帶的數據源。前端

可是,這三種選擇都有各自的問題。普通數據庫通常都是行式存儲,很難得到多維分析但願的高性能,只適用較小數據量。專業數據倉庫有很多是列式存儲的,性能問題不大,可是價格都比較昂貴,建設、擴展和維護成本也都很是高。BI 系統自帶的數據源都比較封閉,只能爲自家的 BI 前端提供支持,沒法爲多個不一樣廠家的前端提供數據服務。java

解決思路與過程

集算器能夠獨立承擔輕量級多維分析後臺的做用,至關於中小型數據倉庫或者數據集市。結構圖以下:

集算器能夠將多維分析的數據事先以列存形式存儲到二進制文件中,稱爲組表。多維分析前端應用拖拽生成 SQL,經過集算器 JDBC 提交。集算器對組表執行 SQL 查詢,將結果返回給多維分析前端。組表文件也可由集算器從各類異構數據源採集數據並計算而來。linux

和普通數據庫方案相比,集算器列存的二進制文件可以直接提高性能。而對於昂貴的專業數據庫和相對封閉的 BI 自帶數據源,集算器能夠提供更加經濟、簡便的解決方案,並可以從各類異構數據源採集數據。web

集算器有三種部署方式:一、集成在前端應用中;二、獨立服務器;三、集羣熱備。下面介紹具體方法。sql

案例場景說明

在下面的案例中,多維分析系統要針對訂單數據作自助分析。爲了簡化起見,多維分析系統前臺用 tomcat 服務器中的 jdbc.jsp 來模擬。Tomcat 安裝在 windows 操做系統的 C:\tomcat6。數據庫

集算器 JDBC 集成在多維分析應用中。jdbc.jsp 模仿多維分析應用系統,產生符合集算器規範的 SQL,經過集算器 JDBC 提交給集算器 SPL 腳本處理。windows

多維分析系統的數據來自於生產數據庫 demo 中的 ORDERS 表,生產庫是 ORACLE 數據庫。多維分析系統不能直接連 demo 數據庫實現分析,以避免給生產數據庫帶來過多的壓力。ORDERS 訂單表是全量數據,集算器 ETL 天天將當天的最新數據同步到組表文件中。日期以訂購日期 ORDERDATE 爲準,假設當前的日期是 2015-07-18。瀏覽器

後臺數據初始化

用下面的 ordersAll.sql 文件在 ORACLE 數據庫中完成 ORDERS 表的建表和數據初始化。緩存

ordersAlltomcat

數據截止到 2017 年 7 月 17 日。

多維分析系統後臺上線初始化的時候,要將 ORDERS 表中的歷史數據同步到集算器的二進制文件中。這是上線前一次性執行的準備工做,上線運行後就不須要執行了。

在集算器中,新建一個數據源 orcl,鏈接 ORACLE 數據庫。用 SPL 語言腳本 etlAll.dfx 將所有數據讀取到集算器組表文件 orders.ctx 中。SPL 腳本以下:

A B
1 =connect(「orcl」) =A1.cursor@d(「select ORDERDATE,CUSTOMERID,EMPLOYEEID,ORDERID,AMOUNT from ORDERS order by ORDERDATE,CUSTOMERID,EMPLOYEEID,ORDERID」)
2 =file(「C:/tomcat6/webapps/DW/WEB-INF/data/orders.ctx」)
3 =A2.create(#ORDERDATE,#CUSTOMERID,#EMPLOYEEID,#ORDERID,AMOUNT)
4 =A3.append(B1) >A1.close()

Orders.ctx 是組表文件,默認是採用列式存儲的,支持任意分段的並行計算,能夠有效提高查詢速度。生成組表的時候,要注意數據預先排序和合理定義維字段。本例中,按照常常過濾、分組的字段,將維字段肯定爲:ORDERDATE,CUSTOMERID,EMPLOYEEID, ORDERID。

從 ORACLE 中取得數據的時候,要按照維字段排序。由於 ORDERDATE,CUSTOMERID,EMPLOYEEID 對應的重複數據多,因此放在前面排序;ORDERID 對應的重複數據少,因此放在後面排序。

B1 單元格中數據庫遊標的 @d 選項,表示從 ORACLE 數據庫中取數的時候將 numeric 型數據轉換成 double 型,精度對於金額這樣的常見數值徹底足夠了。若是沒有這個選項就會默認轉換成 big decimal 型數據,計算性能會受到較大影響。

ETL 過程

多維分析系統上線以後,要天天晚上定時同步當天最新的數據。咱們假設當天日期是 2015-07-18。用下面的 ordersUpdate.sql 文件在 ORACLE 數據庫給 ORDERS 表增長當天的數據,模擬數據的增量。

ordersUpdate

用 SPL 語言腳本 etlUpdate1.dfx 將當天數據增量補充到集算器組表文件 orders.ctx 中。SPL 腳本以下:

A B C
1 =connect(「orcl」)
2 =A1.cursor@d(「select ORDERDATE,CUSTOMERID,EMPLOYEEID,ORDERID,AMOUNT from ORDERS where ORDERDATE=? order by ORDERDATE,CUSTOMERID,EMPLOYEEID,ORDERID」,etlDate)
3 =file(「C:/tomcat6/webapps/DW/WEB-INF/data/orders.ctx」)
4 =A3.create() =A4.append(A2) =A3.rollback()
5 >A1.close()

etlUpdate.dfx 的輸入參數是 etlDate,也就是須要新增的當天日期。

B4 單元格直接將新數據追加到組表文件中。由於第一個排序字段是 orderdate,因此追加新數據不會影響排序。若是第一個排序字段不是 orderdate,就要從新排序。

C4 中的 rollback 是回滾函數,若 B4 執行 append 過程當中,出現錯誤,那麼將執行回滾操做,恢復到 append 操做以前的組表狀態。正常執行完畢,則不會回滾。

etlUpdate1.dfx 腳本能夠用 windows 或者 linux 命令行的方式執行,結合定時任務,能夠定時執行。也能夠用 ETL 工具來定時調用。

windows 命令行的調用方式是:

C:\Program Files\raqsoft\esProc\bin>esprocx.exe C: \etlUpdate1.dfx

linux 命令是:

/raqsoft/esProc/bin/esprocx.sh /esproc/ etlUpdate1.dfx

應用結構一:應用集成計算

集算器 JDBC 集成在多維分析的應用中,接收到 SQL 後查本地文件 orders.ctx 返回結果。

一、下面壓縮文件中的 DW 目錄複製到 tomcat 的應用目錄。

DW

目錄結構以下圖:

配置文件在 classes 中,在官網上獲取的受權文件也要放在 classes 目錄中。集算器的 Jar 包要放在 lib 目錄中(須要哪些 jar 請參照集算器教程)。

修改 raqsoftConfig.xml 中的主目錄配置:

<mainPath>C:\\tomcat6\\webapps\\DW\\WEB-INF\\data</mainPath>

配置好主目錄後,orders.ctx 就能夠不寫全路徑名,直接寫 from orders.ctx 便可。

二、編輯 DW 目錄中的 jdbc.jsp,模擬前臺界面提交 sql 展示結果。

<%@ page language=」java」 import=」java.util.*」 pageEncoding=」utf-8″%>

<%@ page import=」java.sql.*」 %>

<body>

<%

String driver = 「com.esproc.jdbc.InternalDriver」;

String url = 「jdbc:esproc:local://」;

try {

Class.forName(driver);

Connection conn = DriverManager.getConnection(url);

Statement statement = conn.createStatement();

String sql =」select top 10 ORDERID,CUSTOMERID,EMPLOYEEID,ORDERDATE,AMOUNT from ORDERS.ctx where ORDERDATE=date(‘2015-07-18’) and AMOUNT>100″;

out.println(「Test page v1<br><br><br><pre>」);

out.println(「訂單ID」+」\\\t」+」客戶ID」+」\\\t」+」僱員ID」+」\\\t」+」訂購日期」+」\\\t」+」訂單金額」+」<br>」);

ResultSet rs = statement.executeQuery(sql);

int f1,f6;

String f2,f3,f4;

float f5;

while (rs.next()) {

f1 = rs.getInt(「ORDERID」);

f2 = rs.getString(「CUSTOMERID」);

f3 = rs.getString(「EMPLOYEEID」);

f4 = rs.getString(「ORDERDATE」);

f5 = rs.getFloat(「AMOUNT」);

out.println(f1+」\\\t」+f2+」\\\t」+f3+」\\\t」+f4+」\\\t」+f5+」\\\t」+」<br>」);

}

out.println(「</pre>」);

rs.close();

conn.close();

} catch (ClassNotFoundException e) {

System.out.println(「Sorry,can`t find the Driver!」);

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

%>

</body> 

<%@ page language=」java」 import=」java.util.*」 pageEncoding=」utf-8″%>

<%@ page import=」java.sql.*」 %>

<body>

<%

String driver = 「com.esproc.jdbc.InternalDriver」;

String url = 「jdbc:esproc:local://」;

try {

Class.forName(driver);

Connection conn = DriverManager.getConnection(url);

Statement statement = conn.createStatement();

String sql =」select top 10 ORDERID,CUSTOMERID,EMPLOYEEID,ORDERDATE,AMOUNT from ORDERS.ctx where ORDERDATE=date(‘2015-07-18’) and AMOUNT>100″;

out.println(「Test page v1<br><br><br><pre>」);

out.println(「訂單ID」+」\\t」+」客戶ID」+」\\t」+」僱員ID」+」\\t」+」訂購日期」+」\\t」+」訂單金額」+」<br>」);

ResultSet rs = statement.executeQuery(sql);

int f1,f6;

String f2,f3,f4;

float f5;

while (rs.next()) {

f1 = rs.getInt(「ORDERID」);

f2 = rs.getString(「CUSTOMERID」);

f3 = rs.getString(「EMPLOYEEID」);

f4 = rs.getString(「ORDERDATE」);

f5 = rs.getFloat(「AMOUNT」);

out.println(f1+」\\t」+f2+」\\t」+f3+」\\t」+f4+」\\t」+f5+」\\t」+」<br>」);

}

out.println(「</pre>」);

rs.close();

conn.close();

} catch (ClassNotFoundException e) {

System.out.println(「Sorry,can`t find the Driver!」);

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

}

%>

</body>

能夠看到,jsp 中先鏈接集算器的 JDBC,而後提交執行 SQL。步驟和通常的數據庫徹底同樣,具備很高的兼容性和通用性。對於多維分析工具來講,雖然是界面操做來鏈接 JDBC 和提交 SQL,可是基本原理和 jsp 徹底同樣。

三、啓動 tomcat,在瀏覽器中訪問 http://localhost:8080/DW/jdbc.jsp,查看結果。

還能夠繼續測試以下狀況:

一、分組彙總

sql ="select CUSTOMERID,EMPLOYEEID,sum(AMOUNT) 訂單總額,count(1) 訂單數量 from ORDERS.ctx where ORDERDATE=date(‘2015-07-18’) group by CUSTOMERID,EMPLOYEEID";

二、並行查詢

sql="select /*+ parallel (4) */

top 10 ORDERID,CUSTOMERID,EMPLOYEEID,ORDERDATE,AMOUNT from ORDERS.ctx where ORDERDATE=date(‘2015-07-18’) and AMOUNT>100" 

sql="select /*+ parallel (4) */

top 10 ORDERID,CUSTOMERID,EMPLOYEEID,ORDERDATE,AMOUNT from ORDERS.ctx where ORDERDATE=date(‘2015-07-18’) and AMOUNT>100"

和 ORACLE 相似,集算器簡單 SQL 也支持 /+ parallel (4) / 這樣的並行查詢。

應用結構二:獨立服務器

第一種解決辦法是利用應用服務器的資源。在併發量很大,或者數據量很大的狀況下,應用服務器會出現較大壓力。這種狀況下,推薦用獨立的節點服務器進行數據計算。

集算器 JDBC 接收到 SQL 後,轉給 DW.dfx 程序處理。DW.dfx 調用節點服務器上的 DWServer.dfx 進行計算。DWServer.dfx 把表名換成文件名,查本地文件 orders.ctx 返回結果。

下面的 DWServer 目錄複製到須要的目錄。集算器的節點服務器具有跨平臺的特性,能夠運行在任何支持 Java 的操做系統上,部署方法參見集算器教程。這裏假設放到 windows 操做系統的 C 盤根目錄。

DWServer

一、系統上線以前執行初始化 dfx,將 orders.ctx 文件放到 C:/DWServer/data 目錄中。測試的時候能夠直接將已經生成好的 orders.ctx 複製過去。

二、修改前面的 dfx,將 A1 改成 =file(「C:/DWServer/data/orders.ctx」),另存爲 etlUpdate2.dfx。修改好的 etlUpdate2.dfx 在 c:\DWServer 目錄。

三、打開應用服務器中的 C:\tomcat6\webapps\DW\WEB-INF\dfx\DW.dfx,觀察理解 SPL 代碼。參數 sql 是傳入的 SQL 語句。

A B
1 =callx(「DWServer.dfx」,[sql];[「127.0.0.1:8281」])
2 return A1.ifn()

A1:調用節點機上的 DWServer.dfx。參數是 [sql],中括號表示序列,此時是隻有一個成員的序列。[「127.0.0.1:8281」] 是節點機的序列,採用 IP: 端口號的方式。

A2:返回 A1 調用的結果。由於調用結果是序列,因此要用 ifn 函數找到序列中第一個不爲空的成員,就是 SQL 對應的返回結果。

修改 C:\tomcat6\webapps\DW\WEB-INF\classes\raqsoftConfig.xml 中的以下配置:

<mainPath>C:\\\tomcat6\\\webapps\\\DW\\\WEB-INF\\\dfx</mainPath>

<JDBC>

<load>Runtime,Server</load>

<gateway>DW.dfx</gateway>

</JDBC> 

<mainPath>C:\\tomcat6\\webapps\\DW\\WEB-INF\\dfx</mainPath>

<JDBC>

<load>Runtime,Server</load>

<gateway>DW.dfx</gateway>

</JDBC>

這裏標籤的內容就是 JDBC 網關 dfx 文件。在 BI 系統中調用集算器 JDBC 時,所執行的 SQL 都將交由網關文件處理。若是不配置這個標籤,JDBC 提交的語句會被集算器看成腳本直接解析運算。

四、啓動節點服務器。

運行 esprocs.exe, 以下圖:


點擊配置按鈕,配置相關參數:

點擊肯定後,返回主界面,點擊啓動按鈕。

五、打開 C:\DWServer\dfx\DWServer.dfx,觀察理解 SPL 代碼。

A B C
1 =filename=」C:/DWServer/data/orders.ctx」
2 =sql=replace(sql,」from ORDERS.ctx」,」from 「+filename)
3 =connect() =A3.cursor@x(A2) return B3

A1:定義集算器集文件的絕對路徑。

A2:將文件名替換爲絕對路徑。

A3-C3:鏈接文件系統。執行 SQL 獲得遊標並返回。

服務器方式也能夠和「應用結構一」中同樣配置主目錄,A2 就不用寫絕對路徑了。路徑寫在這裏的 SPL 中,好處是同一個服務器能夠給多套數據表(文件)提供服務。若是不少文件都在主目錄下,會不方便管理。

六、重啓 tomcat,在瀏覽器中訪問 http://localhost:8080/DW/jdbc.jsp,查看結果。

應用結構三:集羣熱備

在併發量不斷增大,或者數據量不斷增長的狀況下,節點服務器能夠進行橫向擴展,應對大併發或大數據量計算的壓力。

一、在另外一臺 window 的機器上再部署一套集算器節點,部署方法和解決方法二略有不一樣,須要配置一下數據分區。兩臺服務器的 IP 地址是 168.0.122 和 192.168.0.176。方法二中的 c:\DWServer 目錄也要複製到另外一臺服務器上。

圖中數據分區名稱配置爲 0,路徑是 c:/DWServer/data。注意,兩個服務器都要配置。

二、改寫 168.0.122 上的 c:/DWServer/dfx/etlUpdate2.dfx,另存爲 etlUpdate3.dfx。

A B C
1 =connect(「orcl」)
2 =A1.cursor@d(「select ORDERDATE,CUSTOMERID,EMPLOYEEID,ORDERID,AMOUNT from ORDERS where ORDERDATE=? order by ORDERDATE,CUSTOMERID,EMPLOYEEID,ORDERID」,etlDate)
3 =file(「C:/ DWServer/data/orders.ctx」)
4 =A3.create() =A4.append(A2) =A3.rollback()
5 >A1.close()
6 =sync([「192.168.0.176:8281″]:」192.168.0.122:8281」;0)

A6 單元格是將更新以後的 orders.ctx 同步到 192.168.0.176 的 0 分區,也就是 C:/ DWServer/data 目錄。[「192.168.0.176:8281」] 是指須要同步的節點機列表,若是有更多的節點機須要同步,能夠寫做:[「IP1:PORT1″,」IP2:PORT2″,」IP3:PORT3」]。

由於這裏有同步的代碼,因此只須要在 192.168.0.122 上執行定時任務 etlUpdate3.dfx 就能夠了。

三、打開應用服務器中的 C:\tomcat6\webapps\DW\WEB-INF\dfx\DW.dfx,修改以下:

A B
1 =callx(「DWServer.dfx」,[sql];[「192.168.0.122:8281″,」192.168.0.176:8281」])
2 return A1.ifn()

A1:調用節點機上的 DWServer.dfx。參數是 [sql],中括號表示序列,此時是隻有一個成員的序列。由於節點機是集羣,因此有兩個 IP 地址。在多併發時 callx 會隨機訪問兩個節點。

四、重啓 tomcat,在瀏覽器中訪問 http://localhost:8080/DW/jdbc.jsp,查看結果。

集算器優點總結

開放的輕量級數據倉庫 / 數據集市

集算器是專業的數據計算中間件(DCM),具有獨立計算的能力,能夠脫離數據庫、數據倉庫爲多維分析系統前端提供數據源服務。

集算器採用列存數據,具有專業數據倉庫的查詢性能,千萬級別的數據量,能夠達到秒級的明細查詢速度。普通數據庫通常都是行存,沒法達到多維分析的性能要求。同時,和專業數據倉庫不一樣,集算器價格都較低,建設、擴展和維護成本都比較小。

集算器是開放的,對多維分析系統前端提供標準的 JDBC 服務。能夠造成平臺式的後臺數據源,爲多個不一樣廠家的前端同時提供數據服務。

組表列存 / 有序壓縮存儲

先進的數據存儲方式,是數據計算中間件(DCM)成功實施的重要保障。

集算器組表採用列存方式存儲數據,對於字段特別多的寬表查詢,性能提高特別明顯。組表採用的列存機制和常規列存是不一樣的。常規列存(好比 parquet 格式),只能分塊以後,再在塊內列存,在作並行計算的時候是受限的。組表的可並行壓縮列存機制,採用倍增分段技術,容許任意分段的並行計算,能夠利用多 CPU 核的計算能力把硬盤的 IO 發揮到極致。

組表生成的時候,要指定維字段,數據自己是按照維字段有序存放的,經常使用的條件過濾計算不依賴索引也能保證高性能。文件採用壓縮存儲,減少在硬盤上佔用的空間,讀取更快。因爲採用了合適的壓縮比,解壓縮佔用的 CPU 時間能夠忽略不計。

組表也能夠採起行存和全內存存儲數據,支持內存數據庫方式運行。

集羣功能

敏捷的集羣能力能夠保證數據計算中間件(DCM)的高性能和高可用性。

集算器節點服務器是獨立進程,能夠接受集算器 JDBC 的計算請求並返回結果。對於併發訪問的狀況,能夠發給多個服務器同時計算,提升併發容量。對於單個大計算任務的狀況,能夠分紅多個小任務,發給多個服務器同時計算,起到大數據並行計算的做用。

集算器集羣計算方案,具有敏捷的橫向擴展能力,併發量或者數據量大時能夠經過快速增長節點來解決。集算器集羣也具有容錯能力,即有個別節點失效時還能確保整個集羣能工做,計算任務能繼續執行完畢,起到多機熱備和保證高可用性的做用。

應用推廣

做爲數據計算中間件(DCM),集算器提供的後臺數據源能夠支持各類前端應用,不只僅限於前端是多維分析的狀況。例如:大屏展現、管理駕駛艙、實時報表、大數據量清單報表、報表批量訂閱等等。

集算器造成的後臺數據源也能夠和數據庫、數據倉庫配合使用。集算器實現的數據計算網關和路由,能夠在集算器緩存數據和數據倉庫之間智能切換,解決數據倉庫沒法知足性能要求的問題。例如:冷熱數據分開計算的場景。具體作法參見《集算器實現計算路由優化 BI 後臺性能》。

相關文章
相關標籤/搜索