在上一期的文章(《五分鐘掌握TDengine時(shí)序數(shù)據(jù)的保留策略》)中,我們知道了TDengine Database是如何按照時(shí)間段對(duì)數(shù)據(jù)進(jìn)行分區(qū)來(lái)管理數(shù)據(jù)的。
接下來(lái),我們和大家一起從產(chǎn)品使用者的視角繼續(xù)向前探索——TDengine中的時(shí)序數(shù)據(jù)到底是如何存儲(chǔ)的?
在那篇文章里,在我們第一次寫(xiě)入數(shù)據(jù)并重啟數(shù)據(jù)庫(kù)服務(wù)后,在vnode xx路徑下看到了這三個(gè)文件。

這哥仨,其實(shí)就是TDengine中廣義上的數(shù)據(jù)文件,也可以說(shuō)它們是一個(gè)數(shù)據(jù)文件組。
從后綴上看,仿佛.data這個(gè)文件就是數(shù)據(jù)文件組中的數(shù)據(jù)文件。而其他二位都是為它保駕護(hù)航的“輔助”。但是這個(gè)感覺(jué)是不夠準(zhǔn)確的,因?yàn)?last文件同樣也會(huì)存儲(chǔ)數(shù)據(jù)。而.head文件則是存儲(chǔ)數(shù)據(jù)塊的索引的文件。
在了解它們之前,首先我們要知道兩個(gè)參數(shù):
1.minRows:數(shù)據(jù)塊中記錄的最小條數(shù),單位為條,默認(rèn)值為100。
2.maxRows:數(shù)據(jù)塊中記錄的最大條數(shù),單位為條,默認(rèn)值為4096。
數(shù)據(jù)塊,是每個(gè).data數(shù)據(jù)文件里存儲(chǔ)數(shù)據(jù)的單位,每一個(gè)數(shù)據(jù)塊都只能存儲(chǔ)一個(gè)表的數(shù)據(jù)。所以上面的參數(shù)描述的意思就是——形成一個(gè)數(shù)據(jù)塊默認(rèn)的最小行數(shù)是100行,最多就是4096行。
那么,對(duì)于一張表來(lái)說(shuō),小于100行的話數(shù)據(jù)會(huì)去哪兒呢?大于4096行的話數(shù)據(jù)又去哪兒了呢?
答案是,.last文件正是表行數(shù)不足100時(shí)數(shù)據(jù)存放的位置;而大于4096行的表會(huì)生成一個(gè)新的數(shù)據(jù)塊。最終在.data文件中,數(shù)據(jù)塊的分布方式如下:

當(dāng)然,這樣講會(huì)比較抽象,我們繼續(xù)用實(shí)例說(shuō)明:
我們假設(shè)創(chuàng)建庫(kù)時(shí)使用的參數(shù)為,maxrows=1000,minrows=100。某庫(kù)中有兩張表A和B,我們向其中分別插入1000行和99行數(shù)據(jù)。然后,我們重啟taosd服務(wù),以上數(shù)據(jù)就會(huì)從內(nèi)存中落盤(pán)到存儲(chǔ)上。這個(gè)時(shí)候.data文件中會(huì)生成1個(gè)數(shù)據(jù)塊,它就是表A的數(shù)據(jù)塊1,里面擁有1000條數(shù)據(jù)。而表B的99條數(shù)據(jù)因?yàn)椴蛔鉳inrows所以就進(jìn)入了.last文件。
接下來(lái),繼續(xù)向它們分別插入1000行和99行,然后重啟taosd服務(wù)落盤(pán)。這個(gè)時(shí)候表A總共擁有2000條數(shù)據(jù),新寫(xiě)入的1000行數(shù)據(jù)會(huì)被寫(xiě)入進(jìn)表A的數(shù)據(jù)塊2。而表B的數(shù)據(jù)量現(xiàn)在已經(jīng)有了198行,大于了100行。于是它們也會(huì)被寫(xiě)入.data文件里面,成為表B的數(shù)據(jù)塊1。
值得注意的是,當(dāng).last文件小于32k的時(shí)候,所有數(shù)據(jù)都只會(huì)追加進(jìn)來(lái)。但是當(dāng).last文件大于32k的時(shí)候,每次落盤(pán).last文件都是重寫(xiě)生成的了——這個(gè)的32k限制是為了防止數(shù)據(jù)的移動(dòng)過(guò)于頻繁。
所以,我們?cè)谧鰷y(cè)試的時(shí)侯會(huì)發(fā)現(xiàn):為什么當(dāng)該表行數(shù)從99到100行以上時(shí),.data文件的大小已經(jīng)增加可.last文件卻沒(méi)有變小。只有當(dāng).last文件大于32k的時(shí)候,才能看到符合我們心理預(yù)期的效果——.last文件把數(shù)據(jù)移到.data文件,.last文件變小,.data文件變大。
以上場(chǎng)景只針對(duì)兩個(gè)表,但其實(shí)放大到100個(gè)表,1000個(gè)表都是一樣的邏輯。盡管每個(gè)vnode內(nèi)存里存儲(chǔ)的大量數(shù)據(jù)分屬于不同的表,但是每次落盤(pán)只要這些表的行數(shù)保證大于minrows,它們都會(huì)落入到.data文件的數(shù)據(jù)塊中。不滿足上述條件的表數(shù)據(jù)被寫(xiě)入.last文件后,繼續(xù)等待新數(shù)據(jù)的寫(xiě)入,直到該表滿足了行數(shù)minrows的大小后,.last文件中該表的數(shù)據(jù)會(huì)被讀入到內(nèi)存,之后一起寫(xiě)入到.data文件中。
最后總結(jié)一下:
.data類文件存儲(chǔ)的是真正的時(shí)序數(shù)據(jù),為多個(gè)數(shù)據(jù)塊構(gòu)成。一個(gè)數(shù)據(jù)塊只屬于一張表,且數(shù)據(jù)塊的順序只與落盤(pán)的先后順序有關(guān)。
.last文件與.data文件一樣,也是存儲(chǔ)時(shí)序數(shù)據(jù)的,只不過(guò).last文件存儲(chǔ)的塊中的數(shù)據(jù)條數(shù)小于minRows。
本篇文章重點(diǎn)講述的是.last與.data文件的關(guān)系。
關(guān)于.head文件,我們會(huì)在后面的文章中講解。在此之前,我們只要知道它是用來(lái)方便查詢數(shù)據(jù)的索引文件就可以了。.head文件的用途是什么?它會(huì)影響到哪些重要的功能?minrows和maxrows的變化會(huì)給性能帶來(lái)多大的影響呢?以上這類問(wèn)題都會(huì)涉及到很廣泛的性能問(wèn)題,我們將會(huì)在今后的日子慢慢討論。
如果不了解TDengine Database的體系架構(gòu),對(duì)于用戶來(lái)說(shuō)很可能是事倍功半的。現(xiàn)在,濤思數(shù)據(jù)的每一期內(nèi)容推送都是在為大家未來(lái)可以事半功倍而做的內(nèi)容沉淀。為了強(qiáng)化關(guān)于TDengine存儲(chǔ)模型的理解,建議大家可以回頭看看這兩篇文章(《這幾個(gè)神秘參數(shù),教你TDengine集群的正確使用方式》,《存儲(chǔ)成本僅為OpenTSDB的1/10,TDengine的最大殺手锏是什么?》),其中的知識(shí)點(diǎn)都不是割裂的。
我們擔(dān)心的不是產(chǎn)品不好用,而是產(chǎn)品沒(méi)用好。



互聯(lián)網(wǎng).png)



-1.png)




.png)


證.png)


伙伴.png)
伙伴.png)
伙伴.png)



