近日,咱們曾發佈測試報告 DolphinDB與InfluxDB對比測試報告,此報告測試於2018年底。當時的結果顯示,DolphinDB Database 的查詢性能領先InfluxDB一到三個數據量級,數據導入性能領先一個數量級,數據導出性能相差不大。時隔一年多,DolphinDB與InfluxDB都作了很多功能和性能上的優化,二者的性能究竟有何變化?咱們從新對DolphinDB和InfluxDB進行對比測試,測試涵蓋數據導入導出、數據查詢和磁盤空間佔用三個方面。測試的數據集也涵蓋了日益流行的物聯網數據集,以及規模更大的金融大數據集。git
1、系統概述
DolphinDBgithub
DolphinDB 是以 C++ 編寫的一款分析型的高性能分佈式時序數據庫,使用高吞吐低延遲的列式內存引擎,集成了功能強大的編程語言和高容量高速度的流數據分析系統,可在數據庫中進行復雜的編程和運算,顯著減小數據遷移所耗費的時間。sql
DolphinDB 經過內存引擎、數據本地化、細粒度數據分區和並行計算實現高速的分佈式計算,內置流水線、 Map Reduce 和迭代計算等多種計算框架,使用內嵌的分佈式文件系統自動管理分區數據及其副本,爲分佈式計算提供負載均衡和容錯能力。數據庫
DolphinDB 支持類標準 SQL 的語法,提供相似於 Python 的腳本語言對數據進行操做,也提供其它經常使用編程語言的 API,在金融領域中的歷史數據分析建模與實時流數據處理,以及物聯網領域中的海量傳感器數據處理與實時分析等場景中表現出色。編程
InfluxDBwindows
InfluxDB 是目前最爲流行的高性能開源時間序列數據庫,由 Go 語言寫成。它的核心是一款定製的存儲引擎 TSM Tree,對時間序列數據作了優化,優先考慮插入和查詢數據的性能。緩存
InfluxDB 使用類 SQL 的查詢語言 InfluxQL,並提供開箱即用的時間序列數學和統計函數;同時對外提供基於 HTTP 的接口來支持數據的插入與查詢性能優化
InfluxDB 容許用戶定義數據保存策略 (Retention Policies) 來實現對存儲超過指定時間的數據進行刪除或者降採樣,被普遍應用於存儲系統的監控數據,IoT 行業的實時數據等場景。負載均衡
2、測試環境
因爲 InfluxDB 集羣版本閉源,在測試中 DolphinDB 與 InfluxDB 均使用單機模式。框架
主機:DELL OptiPlex 7060
CPU :Intel Core i7-8700(6 核 12 線程 3.20 GHz)
內存:32 GB (8GB × 4, 2666 MHz)
硬盤:2T HDD (222 MB/s 讀取;210 MB/s 寫入)
OS:Ubuntu 16.04 LTS
測試使用的 DolphinDB 版本爲 Linux v0.89 (2019.01.31),最大內存設置爲 28GB
。
測試使用的 InfluxDB 版本爲 1.7.5,根據 InfluxDB 官方配置文件中的說明,結合測試機器的實際硬件對配置作了優化,主要將 wal-fsync-delay
調節爲適合機械硬盤的 100ms
,將 cache-max-memory-size
設置爲 28GB
,以及將 series-id-set-cache-size
設置爲 400
。
具體修改的配置詳見附錄中 influxdb.conf
文件。
3、數據集
本報告測試了小數據量級(4.2GB)和大數據量級(270GB)下DolphinDB和InfluxDB的表現狀況,如下是兩個數據的表結構和分區方法:
4.2GB設備傳感器記錄小數據集(csv格式,3千萬條)
咱們使用物聯網設備的傳感器信息做爲小數據集來測試,數據集包含3000個設備在2016年11月15日到2016年11月19日10000個時間間隔上的傳感器時間,設備ID,電池,內存,CPU等時序統計信息。數據集共30,000,000條數據,包含包含一張設備信息表device_info和一張設備傳感器信息記錄表readings。
數據來源:https://docs.timescale.com/v1.1/tutorials/other-sample-datasets
下載地址:https://timescaledata.blob.core.windows.net/datasets/devices_big.tar.gz
如下是readings表在DolphinDB和InfluxDB中的結構:
咱們在 DolphinDB database 中的分區方案是將 time
做爲分區的第一個維度,按天分爲 4 個區,分區邊界爲 [2016.11.15 00:00:00, 2016.11.16 00:00:00, 2016.11.17 00:00:00, 2016.11.18 00:00:00, 2016.11.19 00:00:00]
;再將 device_id
做爲分區的第二個維度,天天一共分 10 個區,最後每一個分區所包含的原始數據大小約爲 100 MB
。
InfluxDB 中使用 Shard Group 來存儲不一樣時間段的數據,不一樣 Shard Group 對應的時間段不會重合。一個 Shard Group 中包含了大量的 Shard, Shard 纔是 InfluxDB 中真正存儲數據以及提供讀寫服務的結構。InfluxDB 採用了 Hash 分區的方法將落到同一個 Shard Group 中的數據再次進行了一次分區,即根據 hash(Series) 將時序數據映射到不一樣的 Shard,所以咱們使用如下語句手動指定每一個 Shard Group 的 Duration,在時間維度上按天分區。
create retention policy one_day on test duration inf replication 1 shard duration 1d default
270GB股票交易大數據集(csv格式,23個csv,65億條)
咱們將紐約證券交易所(NYSE)提供的 2007.08.01 - 2007.08.31 一個月的股市 Level 1 報價數據做爲大數據集進行測試,數據集包含 8000 多支股票在一個月內的交易時間
,股票代碼
,買入價
,賣出價
,買入量
,賣出量
等報價信息。
數據集中共有 65 億(65,6169,3704)條報價記錄,一個 CSV 中保存一個交易日的記錄,該月共 23 個交易日,未壓縮的 CSV 文件共計 270 GB。
數據來源:NYSE Exchange Proprietary Market Data
如下是TAQ表在DolphinDB和InfluxDB中的結構:
在 DolphinDB database 中咱們按date(日期)
,symbol(股票代碼)
進行分區,天天再根據 symbol 分爲 100 個分區,每一個分區大概 120 MB 左右。
在InfluxDB中使用與小數據集相同的策略。
4、數據導入導出測試
1. 導入數據
DolphinDB使用如下腳本導入:
timer { for (fp in fps) { loadTextEx(db, `taq, `date`symbol, fp, ,schema) print now() + ": 已導入 " + fp } }
4.2 GB 設備傳感器記錄小數據集共3 千萬條數據導入用時 20 秒
, 平均速率 150 萬條/秒
。
270 GB 股票交易大數據集共 65 億條數據(TAQ20070801 - TAQ20070831
23 個文件),導入用時 38 分鐘
。
InfluxDB 自己不支持直接導入 CSV,只能經過 HTTP API 或者influx -import
的方式導入,出於導入性能考慮,咱們選擇將 CSV 中的每一行先轉換爲 Line Protocol 格式,如:
readings,device_id=demo000000,battery_status=discharging,bssid=A0:B1:C5:D2:E0:F3,ssid=stealth-net battery_level=96,battery_temperature=91.7,cpu_avg_1min=5.26,cpu_avg_5min=6.172,cpu_avg_15min=6.51066666666667,mem_free=650609585,mem_used=349390415,rssi=-42 1479211200
並添加以下文件頭:
# DDL CREATE DATABASE test CREATE RETENTION POLICY one_day ON test DURATION INF REPLICATION 1 SHARD DURATION 1d DEFAULT # DML # CONTEXT-DATABASE:test # CONTEXT-RETENTION-POLICY:one_day
保存到磁盤中,再經過如下命令導入:
influx -import -path=/data/devices/readings.txt -precision=s -database=test
通過轉換後,4.2 GB 設備傳感器記錄小數據集共3 千萬
條數據導入用時25 分鐘 10 秒
, 平均速率2 萬條/秒
。
將 TAQ 數據插入到 InfluxDB 的過程當中,若是屢次插入時間相同 (1185923302),tag 相同的記錄 (這裏是 symbol, mode, ex),好比下面兩條,即便 value 不一樣 (bid, ofr, bidsiz, ofrsiz),後面的那一條記錄也會覆蓋前面的記錄,最終數據庫中只保留了最後一條記錄。
taq,symbol=A,mode=12,ex=T bid=37,ofr=54.84,bidsiz=1,ofrsiz=1 1185923302 taq,symbol=A,mode=12,ex=T bid=37,ofr=38.12,bidsiz=1,ofrsiz=1 1185923302
要解決這個問題文檔(InfluxDB frequently asked questions | InfluxData Documentation)裏給出了兩種方法,一種是新增一個 tag 來對相同時間的數據設置不一樣的 tag value 手動區分,另外一種是強行微調時間戳使其不一樣。
設置不一樣的 tag value 手動區分這種方法只適用於數據徹底按照時間順序插入的狀況。在使用其餘的編程語言插入數據的過程當中判斷該條記錄的時間戳是否與上一條記錄徹底相同,並在插入數據庫時手動指定不一樣的 tag value 做區分,效率低下且操做繁瑣;若數據並不是徹底按照時間順序插入,則沒法判斷當前的時間點是否已經有數據記錄的存在,是否會覆蓋先前的數據。
咱們在本次測試中使用強行微調時間戳的方法,因爲原有 TAQ 交易記錄的時間精度爲秒,所以咱們能夠在將 CSV 的數據轉換至 Line Protocol 格式的過程當中,在原來精確到秒的時間戳的基礎上,隨機加上一個毫秒值,產生一個新的精度爲毫秒的僞時間戳,以防止數據衝突。
通過轉換後,270 GB 股票交易大數據集所包含的65 億
條數據導入用時65 小時
,平均導入速率2.7 萬條/秒
。
導入性能對好比下表所示:
結果顯示,DolphinDB 的導入速率遠大於 InfluxDB 的導入速率。在導入過程當中還能夠觀察到,隨着時間的推移,InfluxDB 的導入速率不斷降低,而 DolphinDB 保持穩定。並且 InfluxDB 在導入數據時須要先編寫代碼將 CSV 格式文件轉換爲 InfluxDB 的 Line Protocol 格式,複雜繁瑣,還會產生多餘的中間文件佔用大量空間。
2. 導出數據
在 DolphinDB 中使用saveText((select * from readings), '/data/devices/readings_dump.csv')
進行數據導出,用時僅需 28 秒。
在 InfluxDB 中若使用influx -database 'test' -format csv -execute "select * from readings > /data/devices/export_15.csv
進行數據導出內存佔用會超過 30 GB,最終引起fatal error: runtime: out of memory
,最後採用分時間段導出 CSV 的方法。代碼以下所示:
for i in 1{5..8}; do time influx -database 'test' -format csv -execute "select * from readings where '2016-11-$i 00:00:00' <= time and time < '2016-11-$((i+1)) 00:00:00'" > /data/devices/export_$i.csv done
總耗時5 min 31 s。
除性能差距懸殊以外,InfluxDB 的 CSV 數據導出操做複雜,容易發生內存溢出問題,並且導出的 CSV 文件首行無字段名稱,用戶體驗遠不如 DolphinDB。
導出性能對好比下表所示:
5、磁盤空間佔用對比
導入數據後,DolphinDB和InfluxDB佔用空間以下表所示:
小數據集中 DolphinDB 的空間利用率與 InfluxDB 相近,兩款數據庫都對數據進行了壓縮存儲,壓縮率大體處於同一個數量級,在 20% - 30% 之間;大數據集中 InfluxDB 對數據的壓縮效果很差,佔用空間爲 DolphinDB 的兩倍。
6、數據庫查詢性能測試
咱們一共對比了如下八種類別的查詢:
- 點查詢指定某一字段取值進行查詢
- 範圍查詢針對單個或多個字段根據時間區間查詢數據
- 精度查詢針對不一樣的標籤維度列進行數據聚合,實現高維或者低維的字段範圍查詢功能
- 聚合查詢是指時序數據庫有提供針對字段進行計數、平均值、求和、最大值、最小值、滑動平均值、標準差、歸一等聚合類 API 支持
- 對比查詢按照兩個維度將表中某字段的內容從新整理爲一張表格(第一個維度做爲列,第二個維度做爲行)
- 抽樣查詢指的是數據庫提供數據採樣的 API,能夠爲每一次查詢手動指定採樣方式進行數據的稀疏處理,防止查詢時間範圍太大數據量過載的問題
- 關聯查詢對不一樣的字段,在進行相同精度、相同的時間範圍進行過濾查詢的基礎上,篩選出有關聯關係的字段並進行分組
- 經典查詢是實際業務中經常使用的查詢
查詢測試的時間包含磁盤 I/O 的時間,爲保證測試公平,每次啓動程序測試前均經過 Linux 系統命令sync; echo 1,2,3 | tee /proc/sys/vm/drop_caches
分別清除系統的頁面緩存、目錄項緩存和硬盤緩存,啓動程序後依次執行全部查詢語句執行一次。
4.2GB設備傳感器記錄小數據集查詢測試結果以下表所示:
查詢腳本見附錄。
結果顯示,DolphinDB的查詢性能遠超於InfluxDB。在功能上,InfluxDB不如DolphinDB強大,好比:
- InfluxDB不支持對比查詢和錶鏈接,沒法完成許多常規SQL數據庫支持的查詢。
- InfluxDB 不支持對除 time 之外的 tag, field 進行排序,即不能
select * from taq order by <some-field>
,詳見[feature request] ORDER BY tag values · Issue #3954 · influxdata/influxdb。 - InfluxDB中函數的參數只能是某一個 field ,而不能是 field 的表達式(
field1 + field2
等)所以只能用 subquery 先計算出表達式的值再套用函數,很是繁瑣,並且須要在子查詢和父查詢的 where 子句中重複指定時間範圍,不然會從最舊的數據記錄的時間開始一直掃描到當前時間。 InfluxDB 和 DolphinDB 第14個查詢語句的對好比下:
//14. 經典查詢:計算某時間段內高負載高電量設備的內存大小 //DolphinDB select max(date(time)) as date, max(mem_free + mem_used) as mem_all from readings where time <= 2016.11.18 21:00:00, battery_level >= 90, cpu_avg_1min > 90 group by hour(time), device_id //InfluxDB select max(mem_total) from ( select mem_free + mem_used as mem_total from readings where time <= '2016-11-18 21:00:00' and battery_level >= 90 and cpu_avg_1min > 90 ) where time <= '2016-11-18 21:00:00' group by time(1h), device_id
270GB股票交易大數據查詢測試結果以下表所示:
查詢腳本見附錄。
結果顯示,某些查詢,二者的性能差異不大,但某些查詢,DolphinDB比InfluxDB快將近100到200倍。
在測試中,咱們發現:
- InfluxDB在第2個查詢中,對於where條件中選擇的多個非連續的時間分區返回的結果爲空,而不是各個時間分區的結果的總和。InfluxDB中第2個查詢的代碼以下所示:
//2. 範圍查詢:查詢某時間段內的某些股票的全部記錄 select symbol, time, bid, ofr from taq where (symbol = 'IBM' or symbol = 'MSFT' or symbol = 'GOOG' or symbol = 'YHOO') and ('2007-08-03 01:30:00' <= time and time < '2007-08-03 01:30:59') //該語句返回的結果不爲空 select symbol, time, bid, ofr from taq where (symbol = 'IBM' or symbol = 'MSFT' or symbol = 'GOOG' or symbol = 'YHOO') and (('2007-08-03 01:30:00' <= time and time < '2007-08-03 01:30:59') or ('2007-08-04 01:30:00' <= time and time < '2007-08-04 01:30:59')) //擴展了時間範圍後,該語句返回的結果反而爲空
- 在InfluxDB中沒法完成第8個查詢。DolphinDB的第8個查詢的代碼以下所示:
//8. 經典查詢:計算某天每一個股票每分鐘最大賣出與最小買入價之差 select symbol, max(ofr) - min(bid) as gap from taq where '2007-08-03' <= time and time < '2007-08-04' and bid > 0 and ofr > bid group by symbol, time(1m)
InfluxDB會拋出異常,ERR: mixing multiple selector functions with tags or fields is not supported
,即不能在select語句中同時使用max和min函數,而DolphinDB能夠正常執行。
- InfluxDB 對時間進行 group by 以後返回的結果包含了全部的時間段,即便當前時間段內無有效數據也返回(以下所示),對於稀疏數據增長了處理複雜度且下降性能,而DolphinDB只返回包含有效數據的時間段。
2007-07-31T23:02:00Z 22.17 54.84 2007-07-31T23:03:00Z 2007-07-31T23:04:00Z 2007-07-31T23:05:00Z 2007-07-31T23:06:00Z 2007-07-31T23:07:00Z 2007-07-31T23:08:00Z 37 38.12 2007-07-31T23:09:00Z 2007-07-31T23:10:00Z 37.03 38.12
7、其餘方面的比較
DolphinDB 除了在基準測試中體現出優越的性能以外,還具備以下優點:
- 語言上,InfluxDB 經過 InfluxQL 來操做數據庫,這是一種類 SQL 語言;而 DolphinDB 內置了完整的腳本語言,不只支持 SQL 語言,並且支持命令式、向量化、函數化、元編程、RPC 等多種編程範式,能夠輕鬆實現更多的功能。
- 數據導入方面,InfluxDB 對於特定文件格式數據例如 CSV 文件的批量導入沒有很好的官方支持,用戶只能經過開源第三方工具或本身實現文件的讀取,規整爲 InfluxDB 指定的輸入格式,再經過 API 進行批量導入。單次只能導入 5000 行,不只操做複雜,效率也極其低下;而DolphinDB提供了ploadText、loadText、loadTextEx函數,能夠直接在腳本中導入CSV文件,對用戶更加友好,而且效率更高。
- 功能上,InfluxDB不支持錶鏈接,部分常規查詢沒法完成;而DolphinDB不只支持經常使用的錶鏈接功能,還對asof join和window join等非同時鏈接作了不少性能優化。
- InfluxDB對時間序列的分組(group by)的最大分組是星期(week);而DolphinDB支持對全部內置時間類型進行分組,最大單位爲月(month)。InfluxDB在查詢中函數的參數只能是某一個字段,不能是字段的表達式,而DolphinDB無此限制。
- DolphinDB提供了600多個內置函數,可知足金融領域的歷史數據建模與實時流數據處理以及物聯網領域中的實時監控與實時分析處理等不一樣場景的需求,而且大部分聚合函數、處理時序數據須要的領先、滯後、累計窗口、滑動窗口函數都作了性能優化。
- DolphinDB 的集羣版本支持事務,並且在一個分區的多個副本寫入時,保證強一致性。
在本次的全部測試項目中,DolphinDB 表現更出色,主要測試結論以下:
- 數據導入方面,小數據集狀況下 DolphinDB 的導入性能是 InfluxDB 的 75 倍 ,大數據集的狀況下導入性能大約是其 100 倍 ,且 InfluxDB 原生不支持 CSV 導入,須要手動轉換爲 Line Protocol 格式。
- 數據導出方面,DolphinDB 的性能是 InfluxDB 的 11 倍 左右,且 InfluxDB 在導出大批量數據爲 CSV 格式時容易產生內存溢出問題。
- 磁盤空間佔用方面,DolphinDB 佔用的空間老是小於等於 InfluxDB 佔用的空間。
- 查詢功能方面,InfluxDB 不支持對比查詢,不支持錶鏈接,不支持對除 time 之外的 tag, field 進行排序,且函數的參數只能是某一個 field ,而不能是 field 的表達式,功能上有極大的限制,有多個測試樣例沒法在 InfluxDB 中實現;而 DolphinDB 對數據的處理則更加的靈活、方便。
- 查詢性能方面,DolphinDB 在 2 個 測試樣例中性能超過 InfluxDB 1000多倍 ;在 6 個 測試樣例中性能超過 InfluxDB 50多倍 ;在 2 個 測試樣例中性能爲 InfluxDB 10多倍 ; 其他全部測試樣例性能也所有優於 InfluxDB。
附錄
數據預覽(取前20行)
- readings
- readings(Line Protocol)
- readings錶轉換爲Line Protocol腳本
- TAQ
- TAQ(Line Protocol)
- TAQ錶轉換爲Line Protocol腳本
DolphinDB
InfluxDB