從《寫入性能:TDengine 最高達到 InfluxDB 的 10.3 倍,TimeScaleDB 的 6.74 倍》、《查詢性能:TDengine 最高達到了 InfluxDB 的 37 倍、 TimescaleDB 的 28.6 倍》兩篇文章中,我們發現,TDengine 不僅在寫入和查詢性能上超越了 InfluxDB 和 TimescaleDB,在數據處理過程的資源消耗也比兩大時序數據庫要更低。本篇文章將會從 TDengine( Time Series Database ) 的(de)產品設計角度出(chu)發,為感興趣(qu)的(de)小伙伴分析一下 TDengine 性能強(qiang)消耗低的(de)原因(yin)。
為什么 TDengine 的“寫入強,開銷低”?
“客(ke)(ke)戶端(duan)上(shang) TDengine 對(dui) CPU 的需求大(da)于 TimescaleDB 和 InfluxDB, 而 InfluxDB 的寫入壓力基(ji)本上(shang)完全集(ji)中在(zai)服(fu)務端(duan),這種模式很容易導致服(fu)務端(duan)成為(wei)瓶頸。TDengine 在(zai)客(ke)(ke)戶端(duan)的開銷(xiao)最大(da),峰值瞬間(jian)達到了 56%,然后快速回(hui)落。綜(zong)合服(fu)務器與客(ke)(ke)戶端(duan)的資(zi)源開銷(xiao)來(lai)看,TDengine 寫入持續時間(jian)更短,在(zai)系統整體 CPU 開銷(xiao)上(shang) TDengine 仍然具有相當大(da)的優勢。”
在 TSBS 測試報告全部的(de) cpu-only 五個場(chang)景(jing)(jing)中(zhong),TDengine 寫(xie)(xie)入(ru)(ru)(ru)性(xing)能均優(you)于 TimescaleDB 和 InfluxDB。相對(dui)于 TimescaleDB,TDengine 寫(xie)(xie)入(ru)(ru)(ru)速(su)度最領先(xian)的(de)場(chang)景(jing)(jing)是其 6.7 倍(場(chang)景(jing)(jing)二),最少也是 1.5 倍(場(chang)景(jing)(jing)五),而且對(dui)于場(chang)景(jing)(jing)四,如果將每個采集點的(de)記(ji)錄條數(shu)由(you) 18 條增加到(dao) 576 條,TDengine 寫(xie)(xie)入(ru)(ru)(ru)速(su)度是 TimescaleDB 的(de) 13.2 倍。相對(dui)于 InfluxDB,TDengine 寫(xie)(xie)入(ru)(ru)(ru)速(su)度最領先(xian)的(de)場(chang)景(jing)(jing)是其 10.6 倍(場(chang)景(jing)(jing)五),最少也是 3.0 倍(場(chang)景(jing)(jing)一)。此外,在保證高效(xiao)寫(xie)(xie)入(ru)(ru)(ru)的(de)情況下(xia),TDengine 在寫(xie)(xie)入(ru)(ru)(ru)過(guo)程中(zhong)消耗的(de) CPU 資源(yuan)和磁盤 IO 開銷(xiao)也是最少的(de)。

通過上圖可以看到,從客戶端負載來說,三個系統中 InfluxDB 計算資源占用最低,對客戶端壓力最小,但這并不能說明 InfluxDB 是三個數據庫當中 CPU 開銷最低的,因為其寫入壓力基本完全集中在了服務端,而這種模式也為 InfluxDB 埋下了一個隱患,如果寫入的數據規模過大,寫入線程會長時間地大量消耗服務器的計算和磁盤IO資源。
與 InfluxDB 相反(fan),TDengine 在(zai)客(ke)戶(hu)端的開銷(xiao)最大,峰值直接沖到了(le) 56%,其(qi)在(zai)客(ke)戶(hu)端的開銷(xiao)比 TimescaleDB 都(dou)多了(le) 1 倍,但在(zai)用時(shi)上,卻比 InfluxDB 和 TimescaleDB 都(dou)小。也因此,從系統(tong)整體的 CPU 開銷(xiao)來看,TDengine 的優勢(shi)仍舊(jiu)非常顯著。
基于產品特點,我們可以從兩個方面分析這種“高寫入,低開銷”的特點。首先,為充分利用數據的時序性等特點,TDengine 采取了“一個數據采集點一張表”的策略,要求對每個數據采集點單獨建表(比如有一千萬個智能電表,就需創建一千萬張表),用來存儲這個數據采集點所采集的時序數據。這種設計對于提升寫入性能來說主要表現在兩個方面:
- 由于不同數據采集點產生數據的過程完全獨立,每個數據采集點的數據源是唯一的,一張表也就只有一個寫入者,這樣就可采用無鎖方式來寫,寫入速度就能大幅提升。
- 對于一個數據采集點而言,其產生的數據是按照時間排序的,因此寫的操作可用追加的方式實現,進一步大幅提高數據寫入速度。
其次,因為 TDengine 的 SQL 解析是在客戶端完成的,這樣一來,其在整個寫入過程中,主要的負載都集中在客戶端,服務器端承擔的壓力就會變得非常小。我們之所以將寫入的負載轉移到客戶端,其原因是客戶應用端的伸縮和擴展操作非常地便捷容易,可操作性更強——在保障服務器有剩余能力的情況下,如果寫入性能不夠,只要增加寫入進程或寫入客戶端即可解決此問題,不再需要增加服務器的設備了。
試想一下,如果不(bu)需(xu)要(yao)變更服務(wu)器數量,那也就不(bu)會涉及(ji)到集群的(de)伸縮(suo)操作(zuo)、資源(yuan)負(fu)載(zai)均衡等復(fu)雜邏輯,整體的(de)寫入(ru)成本自然就會顯著降低。
除(chu)了客戶端 CPU 開銷(xiao)外,三個(ge)系統(tong)對比,TDengine 對服務器的(de)(de)(de) CPU 需(xu)求也是最小(xiao)的(de)(de)(de),峰值(zhi)僅使用了 17% 左右的(de)(de)(de)服務器 CPU 資源。在磁(ci)(ci)盤寫(xie)入(ru)(ru)能(neng)力(li)的(de)(de)(de)消耗(hao)上,InfluxDB 長時(shi)間(jian)消耗(hao)完全部的(de)(de)(de)磁(ci)(ci)盤寫(xie)入(ru)(ru)能(neng)力(li),TimescaleDB 寫(xie)入(ru)(ru)過程對于寫(xie)入(ru)(ru)的(de)(de)(de)消耗(hao)相對 InfluxDB 來說要(yao)更具優勢,但是仍然遠超 TDengine 對磁(ci)(ci)盤寫(xie)入(ru)(ru)能(neng)力(li)的(de)(de)(de)需(xu)求。
如何用最小的計算開銷實現最高的查詢性能?
“從整體 CPU 開銷上來看,TDengine 不僅完成全部查詢(xun)(xun)的時間低于 TimescaleDB 和(he)(he) InfluxDB,在整體上CPU計(ji)算資(zi)源的消耗也(ye)遠小(xiao)于 TimescaleDB 和(he)(he) InfluxDB。在整個(ge)查詢(xun)(xun)過程中,TDengine 內(nei)存(cun)也(ye)始終維持在一個(ge)相對平穩的狀態(tai)。”
基于(yu) TSBS 測試報告我們可(ke)以總結出,查(cha)詢(xun)方面(mian),在(zai)場(chang)景一(yi)(只包含 4 天的數(shu)據)與場(chang)景二的 15 個(ge)不同類型(xing)的查(cha)詢(xun)中(zhong)(zhong),TDengine 的查(cha)詢(xun)平均響應時間(jian)全面(mian)優于(yu) InfluxDB 和 TimescaleDB,而(er)且在(zai)復(fu)雜查(cha)詢(xun)上優勢更為(wei)明顯(xian),同時具有(you)最小(xiao)的計算(suan)資源開(kai)銷。相(xiang)比(bi) InfluxDB,場(chang)景一(yi)中(zhong)(zhong) TDengine 查(cha)詢(xun)性能(neng)是(shi)其(qi) 1.9 ~ 37.0 倍(bei),場(chang)景二中(zhong)(zhong) TDengine 查(cha)詢(xun)性能(neng)是(shi)其(qi) 1.8 ~ 34.2 倍(bei);相(xiang)比(bi) TimescaleDB,場(chang)景一(yi)中(zhong)(zhong) TDengine 查(cha)詢(xun)性能(neng)是(shi)其(qi) 1.1 ~ 28.6 倍(bei),場(chang)景二中(zhong)(zhong) TDengine 查(cha)詢(xun)性能(neng)是(shi)其(qi) 1.2 ~ 24.6 倍(bei)。

在(zai)資源(yuan)開(kai)銷上,TDengine 在(zai)查詢過程中整(zheng)(zheng)(zheng)體(ti)(ti)(ti)(ti) CPU 占(zhan)(zhan)用約 80%,是(shi)(shi)(shi)三個系統中最(zui)高的(de)(de)(de),TimescaleDB 在(zai)查詢過程中瞬時(shi)(shi) CPU 占(zhan)(zhan)用次之,InfluxDB 的(de)(de)(de)穩定 CPU 占(zhan)(zhan)用最(zui)小(但是(shi)(shi)(shi)有較多(duo)的(de)(de)(de)瞬時(shi)(shi)沖高)。從整(zheng)(zheng)(zheng)體(ti)(ti)(ti)(ti) CPU 開(kai)銷上來(lai)看(kan),雖然 InfluxDB 瞬時(shi)(shi) CPU 開(kai)銷大部分是(shi)(shi)(shi)最(zui)低的(de)(de)(de),但是(shi)(shi)(shi)其完成查詢持續時(shi)(shi)間最(zui)長,所以整(zheng)(zheng)(zheng)體(ti)(ti)(ti)(ti) CPU 資源(yuan)消耗最(zui)多(duo)。由(you)于 TDengine 完成全部查詢的(de)(de)(de)時(shi)(shi)間僅為 TimescaleDB 或 InfluxDB 的(de)(de)(de) 1/20,雖然 CPU 穩定值是(shi)(shi)(shi) TimescaleDB 與 InfluxDB 的(de)(de)(de) 2 倍多(duo),但整(zheng)(zheng)(zheng)體(ti)(ti)(ti)(ti)的(de)(de)(de) CPU 計算時(shi)(shi)間消耗只(zhi)有其 1/10 。
用最小的計算開銷實現最高的查詢性能,TDengine 是如何做到的呢?首先,TDengine 對(dui)每個數(shu)據(ju)(ju)采集點(dian)單獨建表(biao)(biao)(biao),但在實際應用(yong)中經常需要對(dui)不同的(de)(de)采集點(dian)數(shu)據(ju)(ju)進行聚合(he)。為高效的(de)(de)進行聚合(he)操(cao)作(zuo)(zuo),TDengine 引入超級表(biao)(biao)(biao)(STable)的(de)(de)概(gai)念。超級表(biao)(biao)(biao)用(yong)來代表(biao)(biao)(biao)一(yi)特定類型的(de)(de)數(shu)據(ju)(ju)采集點(dian),它是包(bao)含多張表(biao)(biao)(biao)的(de)(de)表(biao)(biao)(biao)集合(he),集合(he)里每張表(biao)(biao)(biao)的(de)(de)模式(schema)完全一(yi)致(zhi),但每張表(biao)(biao)(biao)都帶有自己的(de)(de)靜(jing)態標簽(qian),標簽(qian)可(ke)以(yi)有多個,可(ke)以(yi)隨時增加、刪除(chu)和修改。應用(yong)可(ke)通過指定標簽(qian)的(de)(de)過濾條件,對(dui)一(yi)個 STable 下的(de)(de)全部(bu)或(huo)部(bu)分表(biao)(biao)(biao)進行聚合(he)或(huo)統計(ji)操(cao)作(zuo)(zuo),這(zhe)樣就(jiu)大(da)大(da)簡化了應用(yong)的(de)(de)開發。其具(ju)體(ti)流程如下圖所示:

由(you)于 TDengine 在 vnode 內(nei)將標簽數據與時序數據分(fen)離存儲,通過(guo)在內(nei)存里過(guo)濾(lv)標簽數據,就(jiu)可(ke)以先找到需(xu)要參與聚(ju)(ju)(ju)合操(cao)作(zuo)(zuo)的表的集合,這(zhe)樣需(xu)要掃描的數據集就(jiu)會變得大(da)幅減少,聚(ju)(ju)(ju)合計算(suan)速(su)度自然就(jiu)會獲得顯著提升。同時,由(you)于數據分(fen)布在多(duo)個 vnode/dnode,聚(ju)(ju)(ju)合計算(suan)操(cao)作(zuo)(zuo)在多(duo)個 vnode 里并發進(jin)行(xing),這(zhe)又進(jin)一步提升了聚(ju)(ju)(ju)合的速(su)度。
其次,在單表查詢上,當我們要對全部數據集進行查詢時,就需要將查詢請求廣播到所有的節點。試想一下,當我們在業務場景中需要對某個設備進行查詢,這時如果可以不使用標簽過濾,直接查詢對應的設備,查詢效率是不是變得更高了,TDengine 便是如此。在本次(ci)測試(shi)報告中就有幾(ji)個這樣的(de)場景,TDengine 都表現出了很好的(de)查(cha)詢(xun)性(xing)能。
此外,為(wei)(wei)有效(xiao)提升查詢處(chu)(chu)理(li)的(de)(de)性能(neng),針(zhen)對物聯網(wang)數(shu)據(ju)不可(ke)更改的(de)(de)特點,TDengine 會在數(shu)據(ju)塊(kuai)頭部(bu)記錄該數(shu)據(ju)塊(kuai)中存儲數(shu)據(ju)的(de)(de)統(tong)計(ji)(ji)信息:包括最(zui)(zui)大值(zhi)(zhi)、最(zui)(zui)小(xiao)值(zhi)(zhi)、和(he),我們稱之(zhi)為(wei)(wei)預(yu)(yu)計(ji)(ji)算單元。如果查詢處(chu)(chu)理(li)涉及整個數(shu)據(ju)塊(kuai)的(de)(de)全部(bu)數(shu)據(ju),就可(ke)以(yi)直接(jie)使用預(yu)(yu)計(ji)(ji)算結(jie)(jie)果,完全不需要讀取(qu)數(shu)據(ju)塊(kuai)的(de)(de)內容。由于預(yu)(yu)計(ji)(ji)算數(shu)據(ju)量遠小(xiao)于磁盤上存儲的(de)(de)數(shu)據(ju)塊(kuai)數(shu)據(ju)的(de)(de)大小(xiao),對于磁盤 I/O 為(wei)(wei)瓶(ping)頸的(de)(de)查詢處(chu)(chu)理(li),使用預(yu)(yu)計(ji)(ji)算結(jie)(jie)果可(ke)以(yi)極大地減小(xiao)讀取(qu) I/O 壓力,加速查詢處(chu)(chu)理(li)的(de)(de)流程。預(yu)(yu)計(ji)(ji)算機制與 PostgreSQL 的(de)(de)索引 BRIN(block range index)有異(yi)曲同(tong)工之(zhi)妙。
用極致壓縮比實現存儲成本的最大程度降低
“磁(ci)盤(pan)(pan)空(kong)間占(zhan)(zhan)用(yong)方(fang)面(mian),TimescaleDB 在所(suo)有五個(ge)場景(jing)下的數(shu)(shu)據規(gui)模均(jun)顯著(zhu)大于 InfluxDB 和(he) TDengine,并且這(zhe)種差距隨(sui)著(zhu)數(shu)(shu)據規(gui)模增加快速(su)變大。TimescaleDB 在場景(jing)四(si)和(he)場景(jing)五中占(zhan)(zhan)用(yong)磁(ci)盤(pan)(pan)空(kong)間是(shi) TDengine 的 25.6 倍(bei)和(he) 26.9 倍(bei)。在前面(mian)三(san)個(ge)場景(jing)中,InfluxDB 落盤(pan)(pan)后(hou)數(shu)(shu)據文(wen)件規(gui)模與(yu) TDengine 非常接近,但是(shi)在大數(shu)(shu)據規(gui)模的場景(jing)四(si)和(he)場景(jing)五中,InfluxDB 落盤(pan)(pan)后(hou)文(wen)件占(zhan)(zhan)用(yong)的磁(ci)盤(pan)(pan)空(kong)間是(shi) TDengine 的 4.2 倍(bei)和(he) 4.5 倍(bei)。”
當數(shu)據(ju)(ju)寫入磁盤時,TDengine 會(hui)根(gen)據(ju)(ju)系統(tong)配置參數(shu) comp 決定是(shi)否壓(ya)(ya)(ya)縮(suo)(suo)(suo)數(shu)據(ju)(ju)。TDengine 共(gong)提供了三種壓(ya)(ya)(ya)縮(suo)(suo)(suo)選項:無壓(ya)(ya)(ya)縮(suo)(suo)(suo)、一階段(duan)(duan)壓(ya)(ya)(ya)縮(suo)(suo)(suo)和(he)兩階段(duan)(duan)壓(ya)(ya)(ya)縮(suo)(suo)(suo),分別對應(ying) comp 值(zhi)為 0、1 和(he) 2 的情況。一階段(duan)(duan)壓(ya)(ya)(ya)縮(suo)(suo)(suo)根(gen)據(ju)(ju)數(shu)據(ju)(ju)的類型進行了相應(ying)的壓(ya)(ya)(ya)縮(suo)(suo)(suo),壓(ya)(ya)(ya)縮(suo)(suo)(suo)算(suan)法(fa)包括(kuo) delta-delta 編碼(ma)、simple 8B 方法(fa)、zig-zag 編碼(ma)、LZ4 等算(suan)法(fa)。二(er)階段(duan)(duan)壓(ya)(ya)(ya)縮(suo)(suo)(suo)在一階段(duan)(duan)壓(ya)(ya)(ya)縮(suo)(suo)(suo)的基礎上又用通用壓(ya)(ya)(ya)縮(suo)(suo)(suo)算(suan)法(fa)進行了壓(ya)(ya)(ya)縮(suo)(suo)(suo),壓(ya)(ya)(ya)縮(suo)(suo)(suo)率更高。
同時,TDengine 采用的是標簽分離存儲機制,即標簽與數據是分開進行存儲的,這樣就帶來了兩個方面的好處:
- 在存儲操作上占用更小的磁盤空間,表級別的標簽基本上沒有冗余。
- 標簽集中存儲更有利于標簽過濾操作中 IO 訪問的局部性,標簽過濾完成得更快,查詢性能也會變得更好。
此外,對于 TDengine 來說,每個數據塊內部采用的就是列式存儲模式,而且打造了“一個數據采集點一張表”的創新設計,一個數據采集點采集量的變化肯定比多個采集點的采集量變化更慢,壓縮率自然也會變得更高。綜合上述的幾點設計,TDengine 在進行數據處理時提供了很好的壓縮比,幫用戶節約了存儲空間和存儲資源,極大程度上減少了存儲成本浪費。
寫在最后
在產品開發之初,TDengine 就明確了設計方向,即針對時序數據的特點對寫入、存儲、查詢等流程進行設計和優化,在經過幾個版本的不斷迭代加強后,其存儲量大、存儲運維成本低、讀寫性能卓越、壓縮率高等特點越發顯著。這些優勢也體現在企業的具體實踐上,以西門子的數字化解決方案改造項目為例,TDengine 幫助其 SIMICAS? OEM 2.0 版本移除了 Flink、Kafka 以及 Redis,大大簡化了系統架構,節約了運維成本;而在零跑科技的 C11 新車型項目中,TDengine 高壓縮(suo)算法(fa)助力(li)其壓縮(suo)性(xing)能提升了10-20 倍,降低存儲(chu)壓力(li)的(de)同時(shi)也解決(jue)了數(shu)據存儲(chu)成(cheng)本(ben)高的(de)問題。
如果你也面臨著性能和成本難以兩全的數據處理難題,亟需升級數據架構,歡迎添加小T vx:tdengine1,加入 TDengine 用戶(hu)交流群,和更多志(zhi)同道(dao)合的(de)開(kai)發者一(yi)起攻克難關。


























