作為一款高效簡潔的大數(shù)據(jù)平臺,時序數(shù)據(jù)庫 TDengine 的使用體驗極為極為流暢,用戶可以輕松實現(xiàn)數(shù)據(jù)的實時采集、存儲與分析,快速獲取所需的信息和洞察。但在追求最佳實踐的過程中,我們?nèi)孕桕P(guān)注一些關(guān)鍵問題。例如,多個設(shè)備是否應(yīng)該向同一個子表寫入數(shù)據(jù)?在數(shù)據(jù)列過濾查詢與基于標(biāo)簽的過濾查詢之間,效率的差異有多大?此外,如何實現(xiàn)數(shù)據(jù)的高效壓縮也是值得探討的話題。本篇文章將通過具體的案例分析,詳細(xì)講解這些問題,以期幫助大家更深入地理解并高效使用 TDengine。
場景描述
以某智能電表為例,可采集電壓、電流、漏電流、線路端子溫度、有功功率、功率因數(shù)、電量等參數(shù),數(shù)據(jù)每 2 分鐘通過 mqtt 上報一次,通過 TDengine mqtt 可視化連接器進(jìn)行采集,需要對各個累計電量和平均功率進(jìn)行統(tǒng)計。
需求描述
聚焦用電量和平均功率統(tǒng)計分析:
- 查詢用電量
- 年度總耗電量- 昨日用電量
- 用電趨勢,最近 30 天,每天的用電量
- 查詢近 24 小時的設(shè)備功率趨勢,按小時展示,每個小時的數(shù)據(jù)為:該小時單位內(nèi),每個設(shè)備平均功率的總和
建模和存在問題
建模內(nèi)容

建模說明
- 客戶為了將超級表通用化,避免不同表具字段數(shù)目不統(tǒng)一情況,所以用了變量類型、 變量值和變量名稱 3 個字段,將寬表模型變成了單列模型
- 由于變量值包括整型、 浮點型 、離散型等,便將其設(shè)置為字符串類型 ,便于不同類型數(shù)據(jù)都能寫入
- 目前 var_name 列基數(shù)為 {current,power}
- cum_power:當(dāng)前用電量
- power :功率
查詢效果
目前查詢近半年的數(shù)據(jù)每個月的累計值需要近 20 秒。
建模問題點評
客戶的建模方式雖然可以對各種場景適配,但不是最優(yōu)建模,存在以下問題:
- 對于來自同一電表的多個數(shù)據(jù)字段,將其分別處理成多個獨立的插入(insert)操作。在每次插入操作時,系統(tǒng)會利用本地時間生成精確到毫秒的時間戳,確保每個記錄都具有獨特的時間標(biāo)記。然而,在處理大量電表數(shù)據(jù)的情況下,由于缺乏批量插入的策略,這種逐條記錄的插入方法可能會導(dǎo)致性能上的不足。
- 由于將不同采集量的數(shù)值匯總至同一字段,導(dǎo)致數(shù)值之間的差異極大,這不僅影響了一級增量(delta)壓縮的效率,還增加了存儲空間的占用。
- 當(dāng)來自同一電表的不同采集量數(shù)據(jù)被存儲在同一字段中時,由于數(shù)據(jù)量的差異,無法實現(xiàn)在磁盤上的連續(xù)存儲。這種情況在查詢過程中會導(dǎo)致與磁盤的交互次數(shù)顯著增加,從而嚴(yán)重影響查詢效率。
- 由于所有采集值都被存儲在同一個字段中,每次查詢特定采集量時,都需要進(jìn)行數(shù)據(jù)過濾。此外,相對于標(biāo)簽字段,動態(tài)字段通常不支持索引,即使該字段理論上可以索引,但由于列的基數(shù)較低,建立的索引也無法提供有效的性能提升。在數(shù)據(jù)量較大的情況下,這將不可避免地導(dǎo)致查詢速度變慢。
建議建模內(nèi)容
按照寬表形式展示,對于不同類型的設(shè)備,建立不同的超級表。

相關(guān)語句
建表語句
創(chuàng)建超級表
create STABLE if not exists iot.device (ts timestamp, cum_power double, power double,mode TINYINT, note BINARY(500))TAGS ( project_id INT);
創(chuàng)建子表
create table serial_number using device tags(1)
查詢用電量
當(dāng)月總耗電量
select sum(a) from (select spread(cum_power)as a from iot.device where project_id=1 and ts>to_char(now,"yyyy-mm-01") partition by tbname)
當(dāng)年總耗電量
select sum(a) from (select spread(cum_power)as a from iot.device where project_id=1 and ts>to_char(now,"yyyy-01-01") partition by tbname)
昨日用電量
select sum(a) from (select spread(cum_power)as a from iot.device where project_id=1 and ts<timetruncate(now,1d) and ts>=(timetruncate(now,1d)-1d) partition by tbname)
用電趨勢,最近 30 天、每天的用電量
select last(t),sum(a) from (select _wstart as t,spread(cum_power)as a from iot.device where project_id=1 and ts<now and ts>=(timetruncate(now,1d)-30d) partition by tbname interval(1d) order by t) interval(1d)
查詢功率相關(guān)
查詢近 24 小時的設(shè)備功率趨勢——按小時展示每個設(shè)備平均功率的總和
select last(t),sum(a) from(select _wstart as t,avg(power)as a from iot.device where project_id=1 and ts<now and ts>=(timetruncate(now,1h)-24h) partition by tbname interval(1h) order by t)interval(1h)
總結(jié)
TDengine 的高效寫入、查詢性能和數(shù)據(jù)壓縮能力,得益于其創(chuàng)新的“一個設(shè)備一張表”的設(shè)計理念。因此,在進(jìn)行數(shù)據(jù)建模時,我們應(yīng)以這一理念為指導(dǎo),確保系統(tǒng)的長期穩(wěn)定性和性能最優(yōu)化,有效預(yù)防未來數(shù)據(jù)量劇增時可能出現(xiàn)的結(jié)構(gòu)性調(diào)整需求,從而減少潛在的復(fù)雜性和成本。



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



-1.png)







證.png)


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



