乾貨丨時序數據庫DolphinDB與Spark的性能對比測試報告

1. 概述

Spark是基於內存計算的通用大數據並行計算框架,內置多種組件,如批處理、流處理、機器學習和圖處理。Hive是基於Hadoop的數據倉庫,支持類SQL的命令查詢,提升了Hadoop的易用性。Spark與Hive、Hadoop通常是搭配使用,利用Hive中的數據分區可以方便地管理和過濾數據,提高查詢效率。

DolphinDB是C++編寫的高性能分佈式時序數據庫,內置高吞吐低延遲的列式內存引擎,集成了功能強大的編程語言,支持類Python和SQL的腳本語言,可以直接在數據庫中進行復雜的編程和運算。DolphinDB內部用Data Source來抽象分區數據。在Data Source之上,可以完成SQL,機器學習,批處理和流處理等計算任務。一個Data Source既可以是內置的數據庫分區,也可以是外部數據。如果Data Source是內置數據庫的分區,大部分計算都可以在本地完成,極大地提升了計算和查詢效率。

本報告將對DolphinDB、Spark直接訪問HDFS(Spark+Hadoop,下文稱爲Spark)、Spark通過Hive組件訪問HDFS(Spark+Hive+Hadoop,下文稱爲Spark+Hive)三者進行性能對比測試。測試內容包括數據導入、磁盤空間佔用、數據查詢以及多用戶併發查詢。通過對比測試,我們能更深入的瞭解影響性能的主要因素,以及不同工具的最佳應用場景。

2. 環境配置

2.1 硬件配置

本次測試使用了兩臺配置完全相同的服務器(機器1,機器2),各個配置參數如下:

主機:DELL PowerEdge R730xd

CPU:Intel Xeon(R) CPU E5-2650 v4(24核 48線程 2.20GHz)

內存:512 GB (32GB × 16, 2666 MHz)

硬盤:17T HDD (1.7T × 10, 222 MB/s 讀取;210 MB/s 寫入)

網絡:萬兆以太網

OS: CentOS Linux release 7.6.1810 (Core)

2.2 集羣配置

測試的DolphinDB版本爲Linux v0.95。測試集羣的控制節點部署在機器1上,每臺機器上各部署三個數據節點,共六個數據節點。每個數據節點配置8個worker,7個executor,24G內存。

測試的Spark版本爲2.3.3,搭載Apache Hadoop 2.9.0。Hadoop與Spark配置爲完全分佈式模式,機器1爲Master,並且在機器1、機器2上都具有Slave。Hive的版本是1.2.2,機器1、機器2上都具有Hive。元數據存儲在機器1上的MySql數據庫中。Spark 與Spark + Hive使用Standalone模式下的client 方式來提交應用。

測試時,DolphinDB、Spark、Spark+Hive均配置6塊硬盤,不同併發數下使用的CPU、內存總和都相同,都是48個線程,144G內存。Spark與Spark+Hive使用的資源只是對於特定的應用,每個應用有6個executor,在多用戶併發的情況下,Spark、Spark+Hive單個用戶使用的資源會隨着用戶數量增多而減少。不同併發數下每個用戶使用的資源如表1所示。

表1.Spark、Spark+Hive不同併發數下單用戶使用的資源

485cc1bb8aace70b9f01acae9f09a7bc.png

3. 數據集及數據庫設計

3.1 數據集

測試數據集是紐約證券交易所(NYSE)提供的TAQ數據集,包含 8000 多支股票在2007.08.01-2007.08.31一個月內的Level 1報價數據,包含交易時間, 股票代碼, 買入價, 賣出價, 買入量, 賣出量等報價信息。數據集中一共有 65 億(6,561,693,704)條報價記錄,一個 CSV 中保存一個交易日的記錄,該月共23個交易日,未壓縮的 23個CSV 文件共計 277 GB。

數據來源:https://www.nyse.com/market-data/historical

3.2 數據庫設計

表2. TAQ在各個系統中的數據類型。

989cad57de7916b265b6b9cc048ae9b2.png

在 DolphinDB database 中,我們按照date、symbol列組合分區,第一分區使用日期DATE來進行值分區,共23個分區,第二分區使用股票代碼SYMBOL來進行範圍分區,分區數量100個,每個分區大約120M左右。

Spark存儲在HDFS上的數據以23個csv對應23個目錄。Spark+Hive採用兩層分區,第一層分區使用日期DATE列進行靜態分區,第二層分區使用股票代碼SYMBOL進行動態分區。

具體腳本見附錄。

4. 數據導入和查詢測試

4.1 數據導入測試

原始數據均勻地分佈在兩臺服務器的6個硬盤上,這樣可以充分利用集羣中的所有資源。DolphinDB通過異步多節點的方式並行導入數據,Spark與Spark+Hive並行啓動6個應用來讀取數據,把數據存儲到HDFS中。各個系統導入數據的時間如表3所示。各個系統中數據佔用的磁盤空間如表4所示。數據導入腳本見附錄。

表3. DolphinDB、Spark、Spark+Hive導入數據時間

049d04ae72a28c87e3190307b69e796e.png

表4. DolphinDB、Spark、Spark+Hive中數據佔用的磁盤空間

cdbd88e2d29bc620c066c84b9dfa1af8.png

DolphinDB的導入性能明顯優於Spark和Spark+Hive,是Spark的4倍左右,是Spark + Hive的6倍左右。DolphinDB使用C++編寫並且內部有很多優化,極大地利用了磁盤的IO。

DolphinDB佔用的磁盤空間大於Spark與Spark+Hive,大約是他們的2倍,這是因爲Spark和Spark+Hive在Hadoop上都使用Parquet格式,Parquet格式通過Spark寫入到Hadoop上默認使用snappy壓縮。

4.2 數據查詢測試

爲保證測試公平,每個查詢語句要進行多次測試,每次測試之前均通過 Linux 系統命令分別清除系統的頁面緩存、目錄項緩存和硬盤緩存。DolphinDB還清除其內置緩存。

表5中的查詢語句涵蓋了大部分查詢場景,包含分組、排序、條件、聚合計算、點查詢、全表查詢,用來評估DolphinDB、Spark、Spark+Hive在不同用戶數量提交下的性能。

表5. DolphinDB、Spark、Spark+Hive查詢語句

ed6446529cd6a13be4b564ec8ef9abe6.png

4.2.1 DolphinDB與Spark單用戶查詢測試

以下是DolphinDB與Spark單用戶查詢的結果,結果中的耗時爲查詢8次的平均用時。

表6. DolphinDB、Spark單用戶查詢結果

67ddd680339bbd0a70d36d8c93cc5871.png

從結果可以看出,DolphinDB的查詢性能是Spark+HDFS的200倍左右。查詢Q1到Q6都是以DolphinDB的分區字段爲過濾條件,DolphinDB只需要加載指定分區的數據,無需全表掃描,而Spark從Q1到Q6都需要全表掃描,耗費大量的時間。對於查詢Q7,DolphinDB和Spark都需要全表掃描,但是DolphinDB只加載相關的列,無需加載所有列,而Spark則需要加載所有數據。由於Query運行時間被數據加載主導,DolphinDB和Spark的性能差距沒有之前的查詢語句的大。

4.2.2 DolphinDB與Spark+Hive單用戶查詢測試

由於DolphinDB的數據經過分區,且在查詢的時候實現謂詞下推,效率明顯高於Spark。此處我們使用Spark搭載Hive組件來訪問HDFS,對比DolphinDB和Spark+Hive的查詢性能。以下是DolphinDB、Spark+Hive單用戶查詢的結果,結果中的耗時爲查詢8次的平均用時。

表7. DolphinDB、Spark+Hive單用戶查詢結果

126746ffe11a9886d0fdb69e0e7d1833.png

結果顯示,DolphinDB的查詢性能明顯優於Spark+Hive,是Spark+Hive的數十倍。與表6的結果相比,Spark+Hive的查詢速度比Spark要快得多,DolphinDB具有的優勢明顯下降了很多。這是因爲Hive對數據進行分區,且在查詢語句的條件帶有分區字段的時候,只加載部分數據,實現數據過濾,提高效率。查詢語句Q7掃描全表的時候會出現內存溢出。

DolphinDB、Spark+Hive都對數據進行了分區,且在加載數據時都可以實現謂詞下推,達到數據過濾的效果,但是DolphinDB的查詢速度優於Spark+Hive。這是因爲Spark+Hive區讀取HDFS上的數據是不同系統之間的訪問,數據要經過序列化、網絡傳輸、反序列化的過程,非常耗時,從而影響性能。DolphinDB的大部分計算都在本地完成,減少了數據傳輸,因此更加高效。

4.2.3 DolphinDB與Spark計算能力對比

上面DolphinDB分別與Spark、Spark+Hive的查詢性能對比,由於數據分區、查詢時的數據過濾以及傳輸影響了Spark的性能,因此這裏我們先把數據加載到內存中,再進行相關的計算,比較DolphinDB和Spark+Hive。我們省略了Spark+Hive,因爲使用Hive只是爲了數據過濾,讀取HDFS上的數據更加高效,這裏的測試數據已經在內存中。

表8是測試計算能力的語句。每次測試都包含兩個語句,第一個語句是把數據加載到內存中,第二個語句是對內存中的數據進行計算。DolphinDB會自動緩存數據,Spark則通過自己的默認緩存機制重新創建一個臨時表TmpTbl。

表8. DolphinDB與Spark計算能力對比語句

5099c7831c255f31d6465ad4ca8181a6.png

以下是DolphinDB與Spark計算能力的測試結果,結果中的耗時是測試5次的平均用時。

表9. DolphinDB與Spark計算能力測試結果

afdc101929128061f0771b43a8a87395.png

由於數據已經在內存中,對比表6,Spark使用的時間大幅度減少,但是DolphinDB的計算能力仍然比Spark優越。DolphinDB用C++編寫,自己管理內存,比起Spark使用JVM來管理內存更加高效。另外,DolphinDB內置了更高效的算法,提高了計算性能。

DolphinDB的分佈式計算以分區爲單位,計算指定內存的數據。Spark加載整個HDFS上的塊,一個數據塊包含了具有不同symbol值的數據,雖然緩存,但是仍然要篩選,所以在Q1與Q2的比值較大。Spark計算時使用的廣播變量是經過壓縮的,傳輸到其他的executor上再解壓影響性能。

4.2.4 多用戶併發查詢

我們使用表5中的查詢語句,對DolphinDB、Spark、Spark+Hive進行多用戶併發查詢測試。以下是測試結果,結果中的耗時是查詢8次的平均用時。

表10. DolphinDB、Spark、Spark+Hive多用戶併發查詢結果

d7546d50da374bfafa96227bba8d1448.png

圖1. DolphinDB、Spark多用戶查詢結果對比

c0993b3f4be83d815128f56f0f60158c.png

圖2. DolphinDB、Spark+Hive多用戶查詢結果對比

2958ddf62a44f16e10672c97a78ec710.png

從上面的結果可以看出,隨着併發數量的增加,三者的查詢時間逐漸增加。當達到8個用戶併發的時候Spark性能較之前少量的用戶併發情況下顯著下降,Spark 在執行Q7的時候會導致worker死亡。Spark+ Hive在多用戶訪問的時候與DolphinDB一樣,基本保持穩定,但是執行Q7查詢語句的一直會出現內存溢出的異常。

Spark+ Hive的查詢配置與Spark 一樣,因爲有分區的作用,並且可以過濾數據,查詢數據量比較小,所以效率相對於Spark掃描全部數據比較好。

DolphinDB在併發查詢中性能明顯優於Spark 與Spark+ Hive,從上圖可以看出在多用戶併發訪問情況下,隨着用戶數量的增加,DolphinDB相對於Spark 的優勢幾乎是線性增長,相對於Spark + Hive 的優勢基本保持不變,體現了有數據分區在查詢的時候實現數據過濾的重要性。

DolphinDB在多用戶併發的情況下實現了多用戶的數據共享,不像Spark 的數據只是針對於具體的應用。所以在8個併發用戶的情況下,Spark 每個用戶分配到的資源比較少,性能顯著下降。DolphinDB的數據共享可以減少資源的使用,在有限的資源下,把更多的資源留給用戶計算使用,提高用戶併發的效率,增大用戶的併發數量。

5. 小結

在數據的導入方面,DolphinDB可以並行加載,Spark與Spark+Hive 則通過多個應用同時加載來導入數據。DolphinDB的導入速度是Spark 和Spark+ Hive 的4-6倍。在磁盤空間上,DolphinDB佔用的磁盤空間是Spark與Spark+ Hive在Hadoop上佔用的磁盤空間的兩倍左右,Spark與Spark + Hive使用了snappy壓縮。

在數據的SQL查詢方面,DolphinDB的優勢更加明顯。優勢主要來自四個方面:(1)本地化計算,(2)分區過濾,(3)優化的內存計算,(4)跨會話的數據共享。在單用戶查詢情況下,DolphinDB的查詢速度是Spark的幾倍到上百倍,是Spark+ Hive 的幾十倍。Spark 讀取HDFS 是不同的系統之間的調用,其中包含了數據的序列化,網絡,反序列化非常消耗時間,且佔據很多的資源。DolphinDB的SQL查詢大部分是本地化計算,大幅減少了數據傳輸和加載的時間。Spark+ Hive 相對與Spark速度提升很大,主要是因爲Spark + Hive只掃描相關分區的數據,實現了數據的過濾。在剔除本地化和分區過濾的因素後(即所有數據已經在內存中),DolphinDB的計算能力仍然優於Spark數倍。DolphinDB基於分區的分佈式計算效率很高,且對內存的管理比Spark基於JVM的管理更加優秀。Spark的多用戶併發會隨着用戶數量的增多效率逐漸下降,在查詢大數據量的時候用戶過多導致worker 死亡。Spark + Hive的多用戶併發相對比較穩定,但是加載數據過大會出現內存溢出錯誤。 多用戶情況下, DolphinDB可以實現數據的共享,從而減少加載數據使用的資源,查詢速度是Spark的數百倍,是Spark+Hive 的幾十倍。隨着用戶數量的增加,DolphinDB相對於Spark的性能優勢更加明顯。涉及到分區查詢的情況下,Spark+ Hive與DolphinDB顯著提高查詢性能。

Spark是一個非常優秀的通用分佈式計算引擎,在SQL查詢、批處理、流處理、機器學習等方面均有上佳表現。但由於SQL查詢通常只需要對數據計算一次,相對於機器學習需要上百次的迭代,內存計算的優勢無法充分體現。因此,我們更建議將Spark用於計算密集型的機器學習。

在測試過程中,我們也發現DolphinDB是一個非常輕量級的實現,集羣的搭建簡單快速, Spark + Hive+ Hadoop 集羣安裝配置非常複雜。

附錄

附錄1. 數據預覽

875a21dad95a9fd3ed425dd92c3595ab.png

附錄2. Hive創建表語句

CREATE TABLE IF NOT EXISTS TAQ (time TIMESTAMP, bid DOUBLE, ofr DOUBLE, bidsiz INT, ofrsiz INT, mode INT, ex TINYINT, mmid STRING)PARTITIONED BY (date DATE, symbol STRING) STORED AS PARQUET;

附錄3.

DolphinDB導入數據腳本:

fps1、fps2分別代表機器1、2上所有的csv路徑的vector
fps是包含fps1和fps2 的vector
allSites1、allSites2 分別代表機器1、2上數據節點名稱的vector
allSite 是包含 allSites1和allSites2的vector
DATE_RANGE=2007.07.01..2007.09.01
date_schema=database('', VALUE, DATE_RANGE)
symbol_schema=database('', RANGE, buckets)
db=database(FP_DB, COMPO,[date_schema,symbol_schema])
taq = db.createPartitionedTable(schema, `taq, `date`symbol)
for(i in 0..1){
	for(j in 0..(size(fps[i])-1))  {
		rpc(allSites[i][j] % size(allSite[i])],submitJob,"loadData" , "loadData" ,loadTextEx{database(FP_DB), "taq", `date`symbol, fps[i][j]} )
	}
}

Spark與Hive導入數據的配置:

--master local[8]
--executor-memory 24G


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