乾貨丨時序數據庫DolphinDB和TimescaleDB 性能對比測試報告

1、概述

DolphinDBnode

DolphinDB 是以 C++ 編寫的一款分析型的高性能分佈式時序數據庫,使用高吞吐低延遲的列式內存引擎,集成了功能強大的編程語言和高容量高速度的流數據分析系統,可在數據庫中進行復雜的編程和運算,顯著減小數據遷移所耗費的時間。git

DolphinDB 經過內存引擎、數據本地化、細粒度數據分區和並行計算實現高速的分佈式計算,內置流水線、 Map Reduce 和迭代計算等多種計算框架,使用內嵌的分佈式文件系統自動管理分區數據及其副本,爲分佈式計算提供負載均衡和容錯能力。github

DolphinDB database 支持類標準 SQL 的語法,提供相似於 Python 的腳本語言對數據進行操做,也提供其它經常使用編程語言的 API,在金融領域中的歷史數據分析建模與實時流數據處理,以及物聯網領域中的海量傳感器數據處理與實時分析等場景中表現出色。sql

TimescaleDB數據庫

TimescaleDB 是目前市面上惟一的開源且徹底支持 SQL 的時序數據庫。它在 PostgreSQL 數據庫的基礎上進行開發,本質上是一個 PostgreSQL 的插件。編程

TimescaleDB 徹底支持 SQL 且擁有 PostgreSQL 的豐富生態、並針對時間序列數據的快速插入和複雜查詢進行了優化,支持自動分片,支持時間空間維度自動分區,支持多個 SERVER、多個 CHUNK 的並行查詢,內部寫優化(批量提交、內存索引、事務支持、數據倒灌)。windows

然而,目前 TimescaleDB 仍不支持水平擴展(集羣),即不能動態增長新的數據結點以寫入數據(Write clustering for multi-node Timescale deployments is under active development. https://github.com/timescale/timescaledb/issues/9),只支持經過 PostgreSQL 的流複製(streaming replication)實現的只讀集羣(read-only clustering)。緩存

在本報告中,咱們對 TimescaleDB 和 DolphinDB,在時間序列數據集上進行了性能對比測試。測試涵蓋了CSV數據文件的導入導出、磁盤空間佔用、查詢性能等三方面。在咱們進行的全部測試中,DolphinDB 均表現得更出色,主要結論以下:負載均衡

  • 數據導入方面,小數據集狀況下 DolphinDB 的導入性能是 TimescaleDB 的10多倍,大數據集的狀況下導入性能是其100多倍,並且在導入過程當中能夠觀察到隨着導入時間的增長,TimescaleDB 的導入速率不斷降低,而 DolphinDB 保持穩定。
  • 數據導出方面,DolphinDB 的性能是 TimescaleDB 的 3 倍 左右。
  • 磁盤空間佔用方面,小數據集下 DolphinDB 佔用的空間僅僅是 TimescaleDB 的 1/6 ,大數據集下佔用空間僅僅是 TimescaleDB 的 1/17
  • 查詢性能方面,DolphinDB 在4個測試樣例中性能超過 TimescaleDB 50多倍 ;在15個測試樣例中性能爲 TimescaleDB 10 ~ 50 倍 ; 在10個測試樣例中性能是 TimescaleDB 的數倍;僅有2個測試樣例性能低於TimescaleDB。

2、測試環境

TimescaleDB 目前仍未支持可以寫入數據的集羣,所以咱們使用單機進行測試。單機的配置以下。框架

主機: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。測試時使用的 PostgreSQL 版本爲 Ubuntu 10.6-1 on x86_64, TimescaleDB 插件的版本爲 v1.1.1。根據 TimescaleDB 官方指南推薦的性能調優方法,結合測試機器的實際硬件配置,咱們在 https://pgtune.leopard.in.ua/ 網站上生成了配置文件,同時參考了 https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server 這一官方配置指南做了優化,主要將 shared_buffers  effective_cache_size 設置爲 16GB,並根據12線程 CPU 設置了 parallel workers,因爲僅使用一塊機械硬盤,咱們將 effective_io_concurrency 設置爲 1,具體修改的配置詳見附錄中 postgresql_test.conf 文件。

3、數據集

本報告測試了小數據量級(4.2 GB) 和 大數據量級(270 GB) 下 DolphinDB 和 TimescaleDB 的表現狀況:

在小數據量級的測試中咱們預先將硬盤中的分區數據表所有加載到內存中,即在 DolphinDB 中使用 loadTable(memoryMode=true),在 PostgresQL 中使用 pg_prewarm 插件將其加載至 shared_buffers。

在大數據量級的測試中咱們不預先加載硬盤分區表,查詢測試的時間包含磁盤 I/O 的時間,爲保證測試公平,每次啓動程序測試前均經過 Linux 系統命令 sync; echo 1,2,3 | tee /proc/sys/vm/drop_caches 分別清除系統的頁面緩存、目錄項緩存和硬盤緩存。

如下是兩個數據集的表結構和分區方法:

4.2 GB 設備傳感器記錄小數據集(CSV 格式,3 千萬條)

咱們從 TimescaleDB 官方給出的樣例數據集中選擇了 devices_big 做爲小數據集來測試,數據集包含 3000 個設備在 10000 個時間間隔(2016.11.15 - 2016.11.19)上的 傳感器時間, 設備 ID, 電池, 內存, CPU 等時序統計信息。

來源:https://docs.timescale.com/v1.1/tutorials/other-sample-datasets
下載地址:https://timescaledata.blob.core.windows.net/datasets/devices_big.tar.gz

數據集共 3千萬 條數據(4.2 GB CSV),壓縮包內包含一張設備信息表和一張設備傳感器信息記錄表,表結構以及分區方式以下:

device_info 表

readings 表

數據集中device_id這一字段有 3000 個不一樣的值,這些值在 readings 表的記錄中反覆出現,用 text 類型不只佔用大量空間並且查詢效率較低,可是在 TimescaleDB 中咱們難以對這一字段採用 enum 類型,而 DolphinDB 的 Symbol 類型簡單高效地解決了存儲空間和查詢效率這兩大問題。

一樣,對於bssidssid這兩個字段表示設備鏈接的 WiFi 信息,在實際中由於數據的不肯定性,雖然有大量的重複值,但並不適合使用 enum 類型。

咱們在 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

咱們嘗試了在 TimescaleDB 中將device_id做爲分區的第二個維度,但經測試90%查詢樣例的性能反而不如僅由時間維度進行分區,所以咱們選擇僅按照時間維度和按天分爲4個區,該維度和 DolphinDB 的分區方式相同,而device_id這一維度以官方推薦的創建索引的方式(參考https://docs.timescale.com/v1.0/using-timescaledb/schema-management#indexing)來加快查詢速度,以下所示。

create index on readings (device_id, time desc);
create index on readings (ssid, time desc);

270 GB 股票交易大數據集(CSV 格式,23 個 CSV,65 億條)

咱們將紐約證券交易所(NYSE)提供的 2007.08.01 - 2007.08.31 一個月的股市 Level 1 報價數據做爲大數據集進行測試,數據集包含 8000 多支股票在一個月內的交易時間、股票代碼、買入價、賣出價、買入量、賣出量等報價信息。

數據集中共有 65 億(6,561,693,704)條報價記錄,一個 CSV 中保存一個交易日的記錄,該月共 23 個交易日,未壓縮的 CSV 文件共計 270 GB。 來源:https://www.nyse.com/market-data/historical

taq 表

咱們按date(日期),symbol(股票代碼)進行分區,天天再根據 symbol 分爲 100 個分區,每一個分區大概 120 MB 左右。

4、數據導入導出測試

從 CSV 文件導入數據

DolphinDB database 使用如下腳本導入:

timer {
    for (fp in fps) {
        loadTextEx(db, `taq, `date`symbol, fp, ,schema)
        print now() + ": 已導入 " + fp
    }
}

4.2 GB 設備傳感器記錄小數據集共3千萬條數據導入用時 20 秒, 平均速率 1,500,000 條/秒

270 GB 股票交易大數據集共 6,561,693,704 條數據(TAQ20070801 - TAQ20070831 23 個文件),導入用時 38 分鐘

在 TimescaleDB 的導入中,因爲 timescaledb-parallel-copy 工具不支持 CSV 首行爲列名稱,咱們先用 tail -n +2 跳過 CSV 首行,再將文件流寫入其標準輸入。

for f in /data/TAQ/csv/*.csv ; do
    tail -n +2 $f | timescaledb-parallel-copy \
        --workers 12 \
        --reporting-period 1s \
        --copy-options "CSV" \
        --connection "host=localhost user=postgres password=postgres dbname=test sslmode=disable" \
        --db-name test \
        --table taq \
        --batch-size 200000
    
    echo "文件 $f 導入完成"
done

4.2 GB 設備傳感器記錄小數據集共3千萬條數據導入用時 5 分鐘 45 秒, 平均速率 87,000 條/秒

270 GB 股票交易大數據集僅 TAQ20070801, TAQ20070802, TAQ20070803, TAQ20070806, TAQ20070807 五個文件(總大小 70 GB)所包含的 16.7 億 條數據導入用時 24 小時,導入速率 19400 條/秒,預計將數據所有 270 GB 數據導入須要 92 小時

導入性能以下表所示:

結果顯示, DolphinDB 的導入速率遠大於 TimescaleDB 的導入速率,數據量大時差距更加明顯,並且在導入過程當中能夠觀察到隨着導入時間的增長,TimescaleDB 的導入速率不斷降低,而 DolphinDB 保持穩定。

另,TimescaleDB 在導入小數據集後仍需花費 2 min 左右的時間創建索引。

導出數據爲 CSV 文件

在 DolphinDB 中使用 saveText((select * from readings), '/data/devices/readings_dump.csv') 進行數據導出。

在 TimescaleDB 中使用 time psql -d test -c "\COPY (SELECT * FROM readings) TO /data/devices/devices_dump.csv DELIMITER ',' CSV" 進行數據導出。

小數據集的導出性能以下表所示:

5、磁盤空間佔用對比

導入數據後對 TimescaleDB 和 DolphinDB 數據庫佔用空間的分析以下表所示:

DolphinDB 的空間利用率遠大於 TimescaleDB,並且 TimescaleDB 中數據庫佔用的存儲空間甚至大於原始 CSV 數據文件的大小,這主要有如下幾方面的緣由:

  • Timescale 只對比較大的字段進行自動壓縮(TOAST),對數據表沒有自動壓縮的功能,即若是字段較小、每行較短而行數較多,則數據表不會進行自動壓縮,若使用 ZFS 等壓縮文件系統,則會顯著影響查詢性能;而 DolphinDB 默認採用 LZ4 格式的壓縮。
  • TimescaleDB 使用 SELECT create_hypertable('readings', 'time', chunk_time_interval => interval '1 day') 將原始數據錶轉化爲 hypertable 抽象表來爲不一樣的數據分區提供統一的查詢、操做接口,其底層使用 hyperchunk 來存儲數據,經分析發現 hyperchunk 中對時序數據字段的索引共計 0.8 GB,對 device_id, ssid 兩個字段創建的索引共計 2.3 GB。
  • device_id, ssid, bssid 字段有大量的重複值,但 bssid 和 ssid 這兩個字段表示設備鏈接的 WiFi 信息,在實際中由於數據的不肯定性,所以不適合使用 enum 類型,只能以重複字符串的形式存儲;而 DolphinDB 的 Symbol 類型能夠根據實際數據動態適配,簡單高效地解決了存儲空間的問題。

6、查詢測試

咱們一共對比了如下八種類別的查詢:

  • 點查詢指定某一字段取值進行查詢
  • 範圍查詢針對單個或多個字段根據時間區間查詢數據
  • 精度查詢針對不一樣的標籤維度列進行數據聚合,實現高維或者低維的字段範圍查詢功能
  • 聚合查詢是指時序數據庫有提供針對字段進行計數、平均值、求和、最大值、最小值、滑動平均值、標準差、歸一等聚合類 API 支持
  • 對比查詢按照兩個維度將表中某字段的內容從新整理爲一張表格(第一個維度做爲列,第二個維度做爲行)
  • 抽樣查詢指的是數據庫提供數據採樣的 API,能夠爲每一次查詢手動指定採樣方式進行數據的稀疏處理,防止查詢時間範圍太大數據量過載的問題
  • 關聯查詢對不一樣的字段,在進行相同精度、相同的時間範圍進行過濾查詢的基礎上,篩選出有關聯關係的字段並進行分組
  • 經典查詢是實際業務中經常使用的查詢

4.2 GB 設備傳感器記錄小數據集查詢測試

對於小數據集的測試,咱們先將數據表所有加載至內存中。

DolphinDB 使用 loadTable(memoryMode=true) 加載至內存。
TimescaleDB 使用 select pg_prewarm('_hyper_2_41_chunk') 加載至 shared_buffers。

查詢性能以下表所示。查詢腳本見附錄。

對於抽樣查詢,TimescaleDB 中有 tablesample 子句對數據表進行抽樣,參數是採樣的比例,但只有兩種抽樣方式(system, bernoulli),system 方式按數據塊進行取樣,性能較好,但採樣選中的塊內的全部行都會被選中,隨機性較差。bernoulli 對全表進行取樣,但速度較慢。這兩種取樣方式不支持按某一個字段進行取樣;而 DolphinDB 不支持全表取樣,只支持按分區取樣,因爲實現方式不一樣,咱們不進行性能對比。

對於插值查詢,TimescaleDB (PostgreSQL) 無內置插值查詢支持,須要上百行代碼來實現,見 https://wiki.postgresql.org/wiki/Linear_Interpolation ;而 DolphinDB 支持 4 種插值方式,ffill 向後取非空值填充、bfill 向前去非空值填充、lfill 線性插值、nullFill 指定值填充。

對於對比查詢,TimescaleDB 的對比查詢功能由 PostgresQL 內置的 tablefunc 插件所提供的 crosstab() 函數實現,可是從樣例查詢中能夠看出該函數有很大的侷限性:
第一,它須要用戶手動硬編碼第二個維度(行)中全部可能的取值和對應的數據類型,沒法根據數據動態生成,很是繁瑣,所以不能對動態數據或取值多的字段使用。
第二,它只能根據 text 的類型維度進行整理,或者由其它類型的維度事先轉換爲 text 類型。數據量大時該轉換操做效率低下且浪費空間。
而 DolphinDB 原生支持 pivot by 語句,只需指定分類的兩個維度便可自動整理。

對於關聯查詢,雙時間鏈接(asof join)對於時間序列數據分析很是方便。DolphinDB 原生支持 asof join 而 PostgresQL 暫不支持 https://github.com/timescale/timescaledb/issues/271

使用 count(*) 查詢總記錄數時,TimescaleDB 會對全表進行掃描,效率極低。

270 GB 股票交易大數據集查詢測試

在大數據量級的測試中咱們不預先加載硬盤分區表至內存,查詢測試的時間包含磁盤 I/O 的時間,爲保證測試公平,每次啓動程序測試前均經過 Linux 系統命令sync; echo 1,2,3 | tee /proc/sys/vm/drop_caches清除系統的頁面緩存、目錄項緩存和硬盤緩存,啓動程序後依次執行全部測試樣例一遍。

查詢性能以下表所示。查詢腳本見附錄。

7、附錄

  • CSV 數據格式預覽(取前 20 行)

device_info:devices.csv

readings:readings.csv

TAQ:TAQ.csv

  • DolphinDB

安裝、配置、啓動腳本:test_dolphindb.sh

配置文件:dolphindb.cfg

小數據集測試完整腳本:test_dolphindb_small.txt

大數據集測試完整腳本:test_dolphindb_big.txt

  • TimescaleDB

安裝、配置、啓動腳本:test_timescaledb.sh

小數據集測試完整腳本:test_timescaledb_small.sql

大數據集測試完整腳本:test_timescaledb_big.sql

PostgreSQL修改配置:postgresql_test.conf

PostgreSQL完整配置:postgresql.conf

PostgreSQL權限配置:pg_hba.conf

股票代碼的全部可能值:symbols.txt

建立Symbol枚舉類型的SQL語句:make_symbol_enum.sql

生成Symbol枚舉類型的腳本:make_symbol_enum.coffee

  • 測試結果處理腳本

REPL.coffee

相關文章
相關標籤/搜索