QuestDB時序數據庫,性能竟然領先ClickHouse和InfluxDB這麼多

做者:Vlad Ilyushchenko,QuestDB的CTO git

QuestDB (https://questdb.io/https://github.com/questdb/questdb),咱們已經創建了一個專一於性能的開源時間序列數據庫。咱們建立QuestDB初衷是爲了將咱們在超低延遲交易方面的經驗以及咱們在該領域開發的技術方法帶到各類實時數據處理用途中。github

QuestDB的旅程始於2013年的原型設計,咱們在去年HackerNews發佈會期間(https://news.ycombinator.com/item?id=23975807)發表的一篇文章中描述了2013年以後所發生的變化。咱們的用戶在金融服務、物聯網、應用監控和機器學習領域都部署了QuestDB,使時間序列分析變得快速、高效和便捷。 數據庫

什麼是存儲時間序列數據的最佳方式?

在項目的早期階段,咱們受到了基於矢量的append-only系統(如kdb+)的啓發,由於這種模型帶來了速度和簡潔代碼路徑的優點。QuestDB的數據模型使用了咱們稱之爲基於時間的數組,這是一種線性數據結構。這容許QuestDB在數據獲取過程當中把數據切成小塊,並以並行方式處理全部數據。以錯誤的時間順序到達的數據在被持久化到磁盤以前會在內存中進行處理和從新排序。所以,數據在到達數據庫中以前已經按時間排序。所以,QuestDB不依賴計算密集的索引來爲任什麼時候間序列的查詢從新排序數據。數組

這種liner模型與其餘開源數據庫(如InfluxDBTimescaleDB)中的LSM樹或基於B樹的存儲引擎不一樣。數據結構

除了更好的數據獲取能力,QuestDB的數據佈局使CPU可以更快地訪問數據。咱們的代碼庫利用最新CPU架構的SIMD指令,對多個數據元素並行處理同類操做。咱們將數據存儲在列中,並按時間進行分區,以在查詢時從磁盤中提取最小的數據量。架構

數據被存儲在列中,並按時間進行分區app

QuestDBClickHouseInfluxDBTimescaleDB相好比何?

咱們看到時間序列基準測試套件(TSBS https://github.com/timescale/tsbs)常常出如今關於數據庫性能的討論,所以咱們決定提供對QuestDB和其餘系統進行基準測試的能力。TSBS是一個Go程序集,用於生成數據集,而後對讀寫性能進行基準測試。該套件是可擴展的,所以能夠包括不一樣的用例和查詢類型,並在不一樣系統之間進行比較。機器學習

如下是咱們在AWS EC2 m5.8xlarge實例上使用多達14個worker的cpu用例的基準測試結果,該實例有16個內核。佈局

TSBS結果比較了QuestDBInfluxDBClickHouseTimescaleDB的最大獲取吞吐量。性能

咱們使用4個worker達到最大的攝取性能,而其餘系統須要更多的CPU資源來達到最大的吞吐量。QuestDB4個線程達到了959k/秒。咱們發現InfluxDB須要14個線程才能達到最大的攝取率(334k/秒),而TimescaleDB4個線程達到145k/秒。ClickHouse以兩倍於QuestDB的線程達到914k/秒。

當在4個線程上運行時,QuestDBClickHouse1.7倍,比InfluxDB6.5倍,比TimescaleDB6.6倍。

使用4個線程的TSBS基準測試結果:QuestDBInfluxDBClickHouseTimescaleDB每秒獲取的行數。

當咱們使用AMD Ryzen5處理器再次運行該套件時,咱們發現,咱們可以使用5個線程達到每秒143萬行的最大吞吐量。與咱們在AWS上的參考基準m5.8xlarge實例所使用的英特爾至強Platinum相比:

比較QuestDB TSBSAWS EC2AMD Ryzen5上的負載結果

你應該如何存儲亂序的時間序列數據?

事實證實,在攝取過程當中對 "亂序"O3)的數據進行從新排序特別具備挑戰性。這是一個新的方法,咱們想在這篇文章中詳細介紹一下。咱們對如何處理失序攝取的想法是增長一個三階段的方法。

  1. 保持追加模式,直到記錄不按順序到達爲止
  2. 在內存中對暫存區的未提交的記錄進行排序
  3. 在提交時對分類的無序數據和持久化的數據進行覈對和合並

前兩個步驟很直接,也很容易實現,依然只是處理追加的數據,這一點沒變。只有在暫存區有數據的時候,昂貴的失序提交纔會啓動。這種設計的好處是,輸出是向量,這意味着咱們基於向量的閱讀器仍然是兼容的。

這種預提交的排序和合並方式給數據獲取增長了一個額外的處理階段,同時也帶來了性能上的損失。不過,咱們仍是決定探索這種方法,看看咱們能在多大程度上經過優化失序提交來減小性能損耗。

咱們如何分類、合併和提交無序的時間序列數據

處理一個暫存區給了咱們一個獨特的機會來全面分析數據,在這裏咱們能夠徹底避免物理合併,並經過快速和直接的memcpy或相似的數據移動方法來替代。因爲咱們的基於列的存儲,這種方法能夠被並行化。咱們能夠採用SIMD和非時序數據訪問,這對咱們來講是很重要的。

咱們經過優化版本的radix排序對來自暫存區的時間戳列進行排序,所產生的索引被用於並行對暫存區的其他列進行排序。

並行得將列進行排序

如今排序的暫存區是相對於現有分區數據進行映射的。從一開始可能並不明顯,但咱們正試圖爲如下三種類型的每一種創建所需的操做和維度。

失序(O3)排序和合並方案

當以這種方式合併數據集時,前綴和後綴組能夠是持續的數據、失序的數據,或者沒有數據。合併組(Merge Group)是最繁忙的,由於它能夠被持久化的數據、失序的數據、失序的數據和持久化的數據佔據,或者沒有數據。

當明確瞭如何分組和處理暫存區的數據時,一個工人池就會執行所需的操做,在少許的狀況下調用memcpy,其餘都轉向SIMD優化的代碼。經過前綴、合併和後綴拆分,提交的最大活度(增長CPU容量的易感性)能夠經過partition_affected x number_of_columns x 3獲得。

時間序列數據應該多久進行一次排序和合並?

可以快速複製數據是一個不錯的選擇,但咱們認爲在大多數時間序列獲取場景中能夠避免大量的數據複製。假設大多數實時失序的狀況是由傳遞機制和硬件抖動形成的,咱們能夠推斷出時間戳分佈將在必定區間範圍。

例如,若是任何新的時間戳值有很大機率落在先前收到的值的10秒內,那麼邊界就是10秒,咱們稱這個爲滯後邊界。

當時間戳值遵循這種模式時,推遲提交可使失序提交成爲正常的追加操做。失序系統能夠處理任何種類的延遲,但若是延遲的數據在指定的滯後邊界內到達,它將被優先快速處理。

如何比較時間序列數據庫的性能

咱們已經在TimescaleDBTSBS GitHub倉庫中開啓了一個合併請求(Questdb基準支持 https://github.com/timescale/tsbs/issues/157),增長了針對QuestDB運行基準測試的能力。同時,用戶能夠克隆咱們的基準測試fork(https://github.com/questdb/tsbs),並運行該套件以查看本身的結果。

tsbs_generate_data --use-case="cpu-only" --seed=123 --scale=4000 `

    --timestamp-start="2016-01-01T00:00:00Z" --timestamp-end="2016-01-02T00:00:00Z" \

    --log-interval="10s" --format="influx" > /tmp/bigcpu

 

tsbs_load_questdb --file /tmp/bigcpu --workers 4

構建具備受權許可的開源數據庫

在進一步推進數據庫性能的同時,使開發人員可以輕鬆地開始使用咱們的產品,這一點天天都激勵着咱們。這就是爲何咱們專一於創建一個堅實的開發者社區,他們能夠經過咱們的開源分銷模式參與並改進產品。

除了使QuestDB易於使用以外,咱們還但願使其易於審計、審查,提交代碼或其餘的項目貢獻。QuestDB的全部源代碼都在GitHub(https://github.com/questdb/questdb)上以Apache 2.0許可證提供,咱們歡迎對此產品的各類貢獻,包括在GitHub上建立issue或者提交代碼。

© 2021QuestDBSlab提供

相關文章
相關標籤/搜索