測試報告丨DolphinDB與Elasticserach在金融資料集上的效能對比測試

語言: CN / TW / HK

Elasticsearch是一款非常流行的日誌檢索和分析工具,尤其在實時性、擴充套件性、易用性和全文檢索方面有著非常優異的綜合表現。知乎上有一篇文章,Golion:降維打擊!使用ElasticSearch作為時序資料庫,並且取得了非常不錯的效果。很多知乎使用者不禁詢問,Elasticsearch是否可以用於海量金融資料的儲存和分析?

為此我們對DolphinDB和Elasticsearch在不同規模的金融資料集做了綜合的對比測試。測試的內容包括I/O,磁碟空間佔用,記憶體消耗,資料庫查詢(過濾查詢和分組統計)4大項。測試結果沒有意外,在金融資料處理領域表現十分搶眼的時序資料庫DolphinDB完勝Elasticsearch。

  • 分組統計(聚合計算),DolphinDB的表現優於Elasticsearch 10倍左右,而且隨著資料集的增大優勢更明顯。特別的,當測試用例涉及時間型別欄位時,DolphinDB的表現尤為突出。
  • 簡單的過濾查詢,DolphinDB的效能是Elasticsearch的100倍。
  • 在資料匯入方面,Elasticsearch的耗時是DolphinDB的25~75倍,並且隨著資料集增大,有變大的趨勢。
  • 在磁碟空間佔用上,DolphinDB做到了對原始資料的壓縮,而Elasticsearch為了維護文件的索引等資訊(不包括臨時資料),在磁碟上佔用了比原始資料更大的空間。總體差距在10倍左右。

1. 系統介紹

1.1 DolphinDB簡介

DolphinDB是一款分析型的分散式時序資料庫,採用列式儲存,內建流資料處理引擎,平行計算和分散式計算引擎,並提供分散式檔案系統,支援叢集擴充套件。DolphinDB以C++編寫,響應速度極快。提供類SQL和Python的指令碼語言對資料進行操作。提供其它常用程式語言的API,方便與已有應用程式整合。在金融領域中的歷史資料分析建模與實時流資料處理,以及物聯網領域中的海量感測器資料處理與實時分析等場景中表現出色。

1.2 Elasticsearch簡介

Elasticsearch是一個基於Lucene的搜尋伺服器,它是基於本地磁碟儲存資料的分散式系統,並面向文件進行儲存。它和傳統的資料庫有以下類似的對比關係:

Relational DB =>Databases =>Tables => Rows => Columns

Elasticsearch =>Indices=>Types=>Documents => Fields

Elasticsearch叢集可以包含多個索引(Indices),對應DolphinDB的資料庫;每一個索引可以包含多個型別(Types),對應DolphinDB中的表;每一個型別包含多個文件(Documents),對應DolphinDB資料中的行;然後每個文件包含多個欄位(Fields),對應DolphinDB中的列的概念。

2. 系統配置

2.1 硬體配置

本次測試的硬體配置如下:

裝置:DELL OptiPlex 7060

CPU:Inter(R) Core™ i7-8700 CPU @ 3.20GHz,6核心12執行緒

記憶體:32GB

硬碟:2TB機械硬碟

作業系統:Ubuntu 16.04 x64

2.2 環境配置

本次的測試環境為單伺服器下的多節點叢集。為了在單機環境下最大限度地發揮出兩者的效能,需要對DolphinDB以及Elasticsearch進行節點引數的設定。設定DolphinDB的資料節點的個數為4個,單個數據節點最大可用記憶體設定為7 GB。設定Elasticsearch的節點個數為4個,由於Elasticsearch基於Lucene,故需要分配一定記憶體用於Lucene中的段被載入入記憶體中,這對Elasticsearch的效能也會造成很大的影響,本次測試分配8 GB記憶體給Lucene,並設定Elasticsearch中的單個節點的最大可用記憶體為6 GB,且禁止swapping。

3. 測試資料集

為了更加全面地測試DolphinDB和Elasticsearch的效能,我們使用了三個不同規模的股票資料集。資料表CN_Stock中包含了從2008.01.01到2017.12.31中國滬深股票的每日報價資料。資料表US_Prices中包含了從1990.01.02到2016.12.30美國股票市場的每日報價資料。資料表TAQ中包含了2007年8月份的4天美國股票市場level1的高頻資料,共60.6 GB。測試資料集的概況如下表所示:

測試資料集在DolphinDB和Elasticsearch中各個欄位的資料型別如下所示:

(1)CN_Stock表資料型別對映

(2)US_Prices表資料型別對映

(3)TAQ表資料型別對映

4. 分割槽/分片方案

DolphinDB database 提供了靈活的分割槽機制,包括值分割槽,範圍分割槽,列表分割槽,雜湊分割槽和組合分割槽,而Elasticsearch僅支援基於雜湊的分片機制。

在DolphinDB中,對於表CN_Stock,按時間每半年作為一個分割槽,共分成了20個分割槽;對於表US_Prices,按時間每年作為一個分割槽,共分成27個分割槽;對於表TAQ,採用日期、股票程式碼組合分割槽方式,共100個分割槽。副本個數設定為1。

Elasticsearch僅允許定義分片的個數。對於表CN_Stock和表US_Prices,定義分片個數為4;對於表TAQ,定義分片個數為100。副本個數設定為1。

5. 對比測試

我們從資料庫查詢效能、I/O效能、磁碟佔用空間、以及記憶體消耗等方面對DolphinDB和Elasticsearch進行了對比測試。

5.1 資料庫查詢效能測試

DolphinDB指令碼語言支援SQL語法,同時還在其基礎上進行了一定程度的擴充套件,功能更加強大。而在Elasticsearch中,需要安裝外掛來進行SQL語句查詢,同時也提供了基於JSON資料格式的DSL(Domain Specific Language特定領域語言)語言來進行查詢,本次測試採用DSL語言。

Elasticsearch的主要應用場景為搜尋引擎,它支援模糊查詢,對於普通的query,Elasticsearch返回的查詢hits預設僅為10條;對於聚合查詢,其返回的buckets的預設大小也為10。而DolphinDB中每次查詢返回的結果都是全部的結果,不存在模糊查詢的情況。

在Elasticsearch的聚合查詢中,返回結果中存在欄位doc_count_error_upper_bound以及sum_other_doc_count,兩者分別表示沒有在這次聚合中返回、但是可能存在的潛在聚合結果以及這次聚合中沒有統計到的文件數。這也很好的證明了Elasticsearch預設的對於資料查詢操作僅僅只是對資料庫中的部分資料進行模糊查詢,而不是精確的查詢資料庫中的所有資料記錄。為了將兩者放在公平的環境下進行測試,我們需要關閉Elasticsearch的模糊查詢,處理的方式是採用Elasticsearch中的scroll介面以及定義buckets的大小來對控制Elasticsearch返回全部的查詢結果。

在本次測試中,使用了DolphinDB指令碼完成了DolphinDB的查詢效能測試。使用了Python指令碼+DSL來完成Elasticsearch的查詢效能測試。

我們對三張資料表進行了若干種常用的SQL查詢。為了減小偶然因素對結果的影響,本次查詢效能測試對每種查詢操作均進行10次查詢,然後對總時間取平均值,時間以毫秒為單位。各個測試資料集的測試指令碼和結果如下表所示。

(1)CN_Stock表

DolphinDB中的查詢指令碼:

查詢效能測試結果(資料量:5,332,932):

(2)US_Prices表

DolphinDB中的查詢指令碼:

查詢效能測試結果(資料量:50,591,907):

(3)TAQ表

DolphinDB中的查詢指令碼:

查詢效能測試結果(資料量:1,366,036,384):

對於本次的查詢效能測試,我們可以得出以下結論:

(1)在同一張表的所有測試中,DolphinDB的效能都領先Elasticsearch多倍。特別的,對於簡單的過濾查詢,DolphinDB的效能是Elasticsearch的效能的1~2個數量級(見CN_Stock表測試結果的1~4、US_Prices表測試結果的1~4)。

(2)在有關聚合查詢的測試結果中,DolphinDB的效能也都優於Elasticsearch,平均是8~9倍。特別的,按時間分組的聚合查詢中,DolphinDB的效能是Elasticsearch的13~15倍(見CN_Stock表測試結果的5~10,US_Prices表測試結果的5~10)。

(3)在不同的資料規模的相同型別的查詢測試中,我們可以看出隨著資料規模的上升,Elasticsearch的精確查詢的耗時增長幅度遠大於DolphinDB,DolphinDB在不同資料規模下的穩定性優於Elasticsearch。

5.2 I/O效能測試

Elasticsearch提供了_bulk API批量寫入資料的功能。在建立一條新的文件時,首先需要描述文件中可能包含的每個欄位的屬性,資料型別(比如 keyword, text, integer 或 date),以及這些欄位是否需要被 Lucene 索引或儲存。然後Elasticsearch為文件的這些屬性構建相應的對映,並建立倒排索引後形成Lucene中的段。最後通過refresh以及flush機制將倒排索引儲存於磁碟上。其中將記憶體中的倒排索引flush到磁碟上這一過程是決定Elasticsearch效能的關鍵。值得注意的是,雖然Elasticsearch提供了_bulk API 來批量匯入資料,同時也可以設定index.refresh_interval = -1 以及index. number_of_replicas = 0 來進行匯入優化。但是在大批量資料匯入的情況下,當記憶體中的緩衝區滿的時候,仍然會觸發refresh,並且進行flush將資料儲存到磁碟上,因此優化的效果並不是很明顯,Elasticsearch資料匯入緩慢是一個很顯著的缺點。

DolphinDB中建立一張分散式資料表並寫入資料的時候,首先根據分散式資料表的分割槽型別決定不同分割槽的資料寫入的資料節點位置。在分割槽內部,資料是採用列式儲存的方式進行組織,通過節點之間的配合來進行資料的匯入與查詢等操作,資料匯入很快,效能極高。

下表是兩者的資料匯入的I/O效能測試結果,從中可以明顯的觀察到ES/DDB的載入耗時比隨著資料量的上升而增大,特別的,當資料量為60.6GB時,Elasticsearch匯入耗時12個小時以上。資料匯入指令碼見附錄。

5.3 磁碟佔用空間測試

Elasticsearch以其搜尋的高效性與時效性著稱。它是基於Lucene而構建起來的分散式搜尋引擎且對source欄位的內容進行了壓縮處理,但其內部是為每個建立的文件構建倒排索引,並將倒排索引儲存在磁碟中的。因為在磁碟上需要對每個文件新增額外的索引資訊,從而需要更大的儲存空間來存放。而DolphinDB並不需要其餘的索引資訊,真正做到了對原資料的壓縮儲存。測試結果如下表所示。

5.4 記憶體佔用

為了更加全面的觀測到DolphinDB與Elasticsearch在執行過程中的記憶體佔用情況,使用Linux命令htop來監視DolphinDB和Elasticsearch的記憶體佔用情況(記憶體總大小為32GB),結果如下:

5.5 其他方面比較

(1)Elasticsearch通過需要安裝外掛來支援SQL語言,同時其內建的DSL語言是JSON格式,語法比較複雜。而DolphinDB內建了完整的指令碼語言,不僅支援SQL語言,而且支援命令式、向量化、函式化、超程式設計、RPC等多種程式設計正規化,可以輕鬆實現更多的功能。

(2)Elasticsearch的主要用途是提供了一個分散式多使用者能力的全文搜尋引擎,支援模糊查詢,文件(行)不需要固定結構,不同文件可以具有不同欄位集合。而DolphinDB只支援結構化資料。

(3)DolphinDB提供600餘種內建函式,可滿足金融領域的歷史資料建模與實時流資料處理,及物聯網領域中的實時監控與資料實時分析處理等不同的場景需求。提供時序資料處理需要的領先、滯後、累積視窗、滑動視窗等多種指標的函式,且在效能上進行了優化,效能極優。 因而與Elasticsearch相比,DolphinDB擁有更多的適用場景。

(4)Elasticsearch用於時序資料庫中時並不支援表連線,而DolphinDB不僅支援表連線,還對asof join及window join等非同時連線方式做了優化。

(5)DolphinDB對資料寫入支援分散式事務,Elasticsearch不支援事務。

6. 小結

Elasticsearch支援結構化資料和非結構化資料,支援模糊查詢,精確查詢,和聚合計算,適合很多應用場景。但是與DolphinDB這樣專業的時序資料庫相比,無論在功能上和效能上,都有很大的差距。尤其當資料量急劇膨脹,超過實體記憶體上限時,記憶體耗用高、磁碟空間佔用高的缺點暴露出來,對歷史資料計算時效能有明顯的下降。

DolphinDB和Elasticsearch的詳細配置資訊、DolphinDB和Elasticsearch的測試程式碼以及資料匯入指令碼見附錄