從建模思路看 MySQL 和 TDengine 哪個更適合處理量化交易場景下的海量時序數據
瀏覽量: 次 發布日期:2023-08-11 21:12:39
從建模思路看 MySQL 和 TDengine 哪個更適合處理量化交易場景下的海量時序數據
在“量化投資分析”場景中,系統需要從數據接口、網絡上等各個地方獲取證券的信息,其中往往以“實時的價格變動信息”為主要數據,然后再對這些數據進行實時的分析與存儲,供盤中和盤后使用。某企業遇到的問題如下:“我們要對 500 個證券品種進行監控,在開盤時,每 5 秒會更新一次價格數據。這樣算下來的話,每個證券品種一天就會產生 2880 條記錄,如果是 500 個的話,就會有 144 萬條數據。而這,還僅僅是一天中產生的數據。如果使用 MySQL 數據庫,我們該如何設計數據庫和表,來承載這樣的數據量呢?”
從上述場景及問題出發,我們邀請到 TDengine 解決方案架構師進行回復,并產出本篇文章。
144 萬條的數據量對于關系型數據庫來說,確實是個有一定規模的日增量。但從場景上看,上述問題場景還算不上「量化分析投資」的核心,只能稱之為數據抓取的場景。其中抓取對象為「證券」,規模 N = 500, 抓取時間間隔 T = 5s。我們可以假設每次抓取的數據有:
如果要與常見的場景進行類比,可以使用 IT 服務器的運維監控對比。數據如下:
通過上述對比我們可以看到,兩種場景很相似。因此,從概念上講,上述問題場景下的監控數據可以歸納為 metric —— 測量值,并且是隨時間變化的。這是很典型的時序數據,問題場景就是一種經典的時序數據存儲場景。
基于 MySQL 的建模
如果企業要用 MySQL 的話,其實核心要考慮的問題應該是:
基于以上的查詢場景,我們可以選擇兩大路線:
假設你使用 InnoDB 引擎(innodb_百度百科),不管怎么選,為了性能你都會建索引。而 InnoDB 的索引使用 B-Tree 結構,這個數據結構在 Rows > 2000w (經驗值)時,數據寫入會因為索引的維護成本上升而下降,查詢性能也一樣。只是 K = 1 的時候,這個問題才沒那么明顯:
2000w / 2880/day = 6944 days = 19 years
也就是說 1 個證券 1 個 table 的時候,存放 19 個自然年數據時,才會明顯感知到。
當然,我們對這個問題有另外一種處理方法:按照時間(一般以天為單位)在進行分表(或分庫):
這種方式在一定程度上也能有效避免問題,但是分庫分表還會引來查詢側改造的工作量,仍然無法徹底解決問題。但是如果我們換用專用的時序數據庫,就能更好地解決這個問題。
基于 TDengine 建模
兆柏數據恢復公司TDengine 作為國內 Top 的開源時序數據庫,產品定位為「分布式時序數據庫」,產品功能專門針對時序數據場景設計和優化,已經被廣泛運用于金融、車聯網、工業互聯網等時序數據場景中。已經落地的「量化投資分析」場景方案有《TDengine在同花順組合管理業務中的優化實踐》、《TDengine 在弘源泰平量化投資中的實踐》等。
回到上面基于 MySQL 的建模思路,TDengine 的設計里面,也是 1 個證券 1 個 table 的理念,通過超級表(stable)的語法糖,快速并行查詢多個證券的數據;同時針對常見的業務查詢場景做了定向的性能優化,從而保證在「海量」數據的情況下,性能依舊表現堅挺;而且還設置了很多有趣的特性,助力時序處理更加簡單。
標準 SQL 語法
TDengine 支持標準 SQL 語法,比老一代的時序數據庫,具備更好的上手體驗。
動態與靜態數據分離
在 TDengine 當中,超級表(stable)結構引入了標簽(tag)的概念,這樣一來,我們可以把證券的維度信息放在標簽當中,減少數據存儲空間,提升查詢性能。同時,在建模上采用 1 個證券 1 張表的方式,以此保證高性能讀寫。
通過超級表語法糖,TDengine 實現了并行查詢的能力,大大減少 SQL 的復雜度:
以上便是兩種數據庫對于上述問題場景的具體解決思路,你覺得如果是你會選擇哪一種呢?可以在評論區進行留言,一起討論。
總而言之,不管是傳統的關系型數據庫,還是 NoSQL 數據庫,如果我們沒有針對性地去對應時序數據特點,在性能提升上極為有限,只能依靠集群技術,投入更多的計算資源和存儲資源來處理,系統的運營維護成本也會因此急劇上升。如果你也面臨著海量時序數據處理難題,不妨可以加一下小T vx:tdengine1,進入 TDengine 用戶交流群,和大家一起來探討解決路徑。