你肯定遇見過這樣的問題:由于某種原因,現(xiàn)場采集的數(shù)據(jù),傳到應(yīng)用端的時(shí)候少了幾條;恰巧又碰到了強(qiáng)迫癥的客戶。如何解決這種糾結(jié)而又蹂躪的情況呢?
有個(gè)被虐得很慘的客戶找到我們,非常創(chuàng)新地逆向使用TDengine Database的降維(down sample)功能,使其項(xiàng)目瞬間多了一個(gè)非常優(yōu)秀的亮點(diǎn):
「我們公司的產(chǎn)品,絕對按照采集周期完美采集,正常情況下,不會丟失任意一條數(shù)據(jù)!最重要的是,我們的采集周期可以支持到1μs?!?/p>
當(dāng)然,這個(gè)功能不是我們憑空想象,憑空捏造出來的,而是基于真實(shí)的客戶需求產(chǎn)生的。
我們都知道,由于網(wǎng)絡(luò)的原因,導(dǎo)致不可以避免地在傳輸過程中,會丟失某個(gè)時(shí)間戳的數(shù)據(jù);特別是在采集周期特別短的情況下,數(shù)據(jù)量非常大,這種現(xiàn)象就是普遍存在、不可避免的。
但是與我們聯(lián)系的客戶是一家有技術(shù)潔癖的公司,一直追求產(chǎn)品的完美,雖然丟失數(shù)據(jù)這種情況不可避免,但對于他們來說是不能接受的。最開始這個(gè)客戶了解的功能是這樣的:
TDengine Database支持按時(shí)間段進(jìn)行聚合,可以將表中數(shù)據(jù)按照時(shí)間段進(jìn)行切割后聚合生成結(jié)果,比如溫度傳感器每秒采集一次數(shù)據(jù),但需查詢每隔10分鐘的溫度平均值。這個(gè)聚合適合于降維(down sample)操作,語法如下:
SELECT function_list FROM tb_name
[WHERE where_condition]
INTERVAL (interval)
[FILL ({NONE | VALUE | PREV | NULL | LINEAR})]
SELECT function_list FROM stb_name
[WHERE where_condition]
INTERVAL (interval)
[FILL ({ VALUE | PREV | NULL | LINEAR})]
[GROUP BY tags]
聚合時(shí)間段的長度由關(guān)鍵詞INTERVAL指定,官網(wǎng)給出的最短時(shí)間間隔10毫秒(10a)。注:聚合查詢中,能夠同時(shí)執(zhí)行的聚合和選擇函數(shù)僅限于單個(gè)輸出的函數(shù):count、avg、sum 、stddev、leastsquares、percentile、min、max、first、last,不能使用具有多行輸出結(jié)果的函數(shù)。
那么如果采集周期和interval是一樣的,是不是就實(shí)現(xiàn)了補(bǔ)值功能呢?根據(jù)客戶(一家做芯片監(jiān)測廠家)的實(shí)際場景,比如現(xiàn)場的采集周期是1μs,也就是說在1μs的時(shí)間范圍內(nèi),僅有一條數(shù)據(jù),如果丟失了,這個(gè)時(shí)間戳就沒有數(shù)據(jù)。比如有一個(gè)超級表teststb有兩個(gè)子表,id分別為1和2,原始數(shù)據(jù)如下圖所示,可以看到有些時(shí)間點(diǎn)數(shù)據(jù)是丟失的:

然后,我們創(chuàng)新使用這個(gè)函數(shù):
select first(num) from teststb where ts >= "2020-04-17 09:00:00.000000" and ts <="2020-04-17 09:00:00.000010" interval (1u) fill(prev) group by id order by ts;
結(jié)果如下圖所示:

1)interval 的時(shí)間范圍是 1μs,比官網(wǎng)的 10ms 粒度要小,這是為該客戶的場景定制開發(fā)的,在版本 1.6.5.8 中已經(jīng)開放出來了;
2)order by 原來不支持子表之間的排序問題,也為該客戶的場景定制解決,目前可以支持 10 萬條以內(nèi)的記錄進(jìn)行排序;
3)使用 first 函數(shù),取 interval 時(shí)間范圍內(nèi)的第一條數(shù)據(jù),因?yàn)?interval 的時(shí)間范圍和采集周期一致,所以使用 first 得到的就是原來的采樣值;
4)如果此 interval 范圍內(nèi)沒有數(shù)據(jù),也就是采樣值丟失了,根據(jù)物聯(lián)網(wǎng)傳感器數(shù)據(jù)相鄰兩條數(shù)據(jù)之間波動不大的現(xiàn)象,可以使用 fill(prev),也就是說將此時(shí)間戳的數(shù)據(jù),填補(bǔ)為前一條正常采樣的采樣值;
5)但是如果時(shí)間 where 開始的時(shí)間點(diǎn),第一條和前面一條都是 null,則 fill(prev)仍然會是 null,這一點(diǎn)需要注意。
這樣就實(shí)現(xiàn)了,即使在網(wǎng)絡(luò)環(huán)境非常差的情況下,也可以得到接近最真實(shí)現(xiàn)場環(huán)境的采樣數(shù)據(jù),方便對實(shí)際現(xiàn)場進(jìn)行數(shù)據(jù)分析和故障排查。
一個(gè)“天下第一等”的功能就此誕生。
我們喜歡和有趣的人一起,做有趣且有意義的事。因此,有任何“新奇特”的想法,請盡管提給我們,也許你的靈機(jī)一動和奇思妙想能夠讓TDengine Database錦上添花。好看的皮囊千篇一律,希望TDengine Database能成為最有趣的那一個(gè)。
作者:蘇曉慰
研發(fā)支持:李琿



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



-1.png)







證.png)


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



