天天看點

量化交易場景下處理海量時序資料,MySQL和 TDengine模組化方式對比

作者:TDengine濤思資料

在“量化投資分析”場景中,系統需要從資料接口、網絡上等各個地方獲驗證券的資訊,其中往往以“實時的價格變動資訊”為主要資料,然後再對這些資料進行實時的分析與存儲,供盤中和盤後使用。某企業遇到的問題如下:“我們要對 500 個證券品種進行監控,在開盤時,每 5 秒會更新一次價格資料。這樣算下來的話,每個證券品種一天就會産生 2880 條記錄,如果是 500 個的話,就會有 144 萬條資料。而這,還僅僅是一天中産生的資料。如果使用 MySQL 資料庫,我們該如何設計資料庫和表,來承載這樣的資料量呢?”

從上述場景及問題出發,我們邀請到 TDengine 解決方案架構師進行回複,并産出本文。

144 萬條的資料量對于關系型資料庫來說,确實是個有一定規模的日增量。但從場景上看,上述問題場景還算不上「量化分析投資」的核心,隻能稱之為資料抓取的場景。其中抓取對象為「證券」,規模 N = 500, 抓取時間間隔 T = 5s。我們可以假設每次抓取的資料有:

{scrawlTime: '2023-01-01 00:00:00'stock_code: 12345,price: 12.00,volumn: 134,bid_price_1: 12.01,bid_pridce_2: 12.02}           

如果要與常見的場景進行類比,可以使用 IT 伺服器的運維監控對比。資料如下:

{timestamp: '2023-01-01 00:00:00'ip: '172.16.8.1',cpu_usage: 0.81,memory_usage: 0.23}           

通過上述對比我們可以看到,兩種場景很相似。是以,從概念上講,上述問題場景下的監控資料可以歸納為 metric —— 測量值,并且是随時間變化的。這是很典型的時序資料,問題場景就是一種經典的時序資料存儲場景。

基于 MySQL 的模組化

如果企業要用 MySQL 的話,其實核心要考慮的問題應該是

  • 如何保證能夠及時寫入:500 rows/5s = 100 rows/s(但這個基本不是問題)。
  • 如何保證能夠快速查出?從 IT 運維看,常見的查詢包括:查詢單個證券:基于時間範圍查詢:ts in [startTs, endTs)基于監控值的過濾:WHERE bid_price_1 >= 10.00;最新值查詢:ORDER BY ts DESC LIMIT 1查詢多個證券:在單個證券相同的情況下,隻需要更快地傳回,能在 1 個查詢裡傳回更好。基于時間的計算:滑動視窗:如 5 日均線圖狀态視窗:根據成交量分段統計。。。

基于以上的查詢場景,我們可以選擇兩大路線:

  • N 個證券,每 K 個證券,放在 1 個 table 中K = 1 時,相當于 1 個證券 1 個 tableK = N 時,相當于用 1 個 table 存放所有資料

假設你使用 InnoDB 引擎(innodb_百度百科),不管怎麼選,為了性能你都會建索引。而 InnoDB 的索引使用 B-Tree 結構,這個資料結構在 Rows > 2000w (經驗值)時,資料寫入會因為索引的維護成本上升而下降,查詢性能也一樣。隻是 K = 1 的時候,這個問題才沒那麼明顯:

2000w / 2880/day = 6944 days = 19 years

也就是說 1 個證券 1 個 table 的時候,存放 19 個自然年資料時,才會明顯感覺到。

當然,我們對這個問題有另外一種處理方法:按照時間(一般以天為機關)在進行分表(或分庫):

  • N 個 證券,每 K 個證券,每 D 天 放在 1 個 table當 K = 1 時D = 1,相當于 1 個證券 1 天 1 個 table。1 年下來有 N/K x 365 = 182,500 個 table。D = 30, 相當于 1 個證券 30 天 1 個 table。1 年下來 有 6083 個 table。D = INF,相當于 1 個證券 1 個 table。K = N 時,相當于用 1 個 table 存放所有資料D = 1,相當于所有證券 1 天 1 個 table。1 年下來 365 個 table。D = 30, 相當于 30 天 1 個 table。 1 年下來 12 個 table。D = INF,相當于 1 個 table。

這種方式在一定程度上也能有效避免問題,但是分庫分表還會引來查詢側改造的工作量,仍然無法徹底解決問題。但是如果我們換用專用的時序資料庫,就能更好地解決這個問題。

基于 TDengine 模組化

TDengine 作為國内 Top 的開源時序資料庫,産品定位為「分布式時序資料庫」,産品功能專門針對時序資料場景設計和優化,已經被廣泛運用于金融、車聯網、工業網際網路等時序資料場景中。已經落地的「量化投資分析」場景方案有《TDengine在同花順組合管理業務中的優化實踐》、《TDengine 在弘源泰平量化投資中的實踐》等。

回到上面基于 MySQL 的模組化思路,TDengine 的設計裡面,也是 1 個證券 1 個 table 的理念,通過超級表(stable)的文法糖,快速并行查詢多個證券的資料;同時針對常見的業務查詢場景做了定向的性能優化,進而保證在「海量」資料的情況下,性能依舊表現堅挺;而且還設定了很多有趣的特性,助力時序處理更加簡單。

标準 SQL 文法

TDengine 支援标準 SQL 文法,比老一代的時序資料庫,具備更好的上手體驗。

量化交易場景下處理海量時序資料,MySQL和 TDengine模組化方式對比

動态與靜态資料分離

在 TDengine 當中,超級表(stable)結構引入了标簽(tag)的概念,這樣一來,我們可以把證券的次元資訊放在标簽當中,減少資料存儲空間,提升查詢性能。同時,在模組化上采用 1 個證券 1 張表的方式,以此保證高性能讀寫。

量化交易場景下處理海量時序資料,MySQL和 TDengine模組化方式對比

通過超級表文法糖,TDengine 實作了并行查詢的能力,大大減少 SQL 的複雜度:

量化交易場景下處理海量時序資料,MySQL和 TDengine模組化方式對比

以上便是兩種資料庫對于上述問題場景的具體解決思路,你覺得如果是你會選擇哪一種呢?可以在評論區進行留言,一起讨論。

總而言之,不管是傳統的關系型資料庫,還是 NoSQL 資料庫,如果我們沒有針對性地去對應時序資料特點,在性能提升上極為有限,隻能依靠叢集技術,投入更多的計算資源和存儲資源來處理,系統的營運維護成本也會是以急劇上升。

繼續閱讀