在處理大規(guī)模時序數(shù)據(jù)時,數(shù)據(jù)切分查詢是一種重要的技術(shù)手段。TDengine時序數(shù)據(jù)庫提供了PARTITION BY子句,支持按維度對數(shù)據(jù)進行切分,然后在每個切分空間內(nèi)進行獨立計算。本文將詳細介紹數(shù)據(jù)切分查詢的原理和應(yīng)用。
一、數(shù)據(jù)切分查詢概述
1.1 什么是數(shù)據(jù)切分查詢
數(shù)據(jù)切分查詢是指將數(shù)據(jù)按照一定維度進行分組,每個分組形成一個獨立的數(shù)據(jù)空間,然后在這些空間內(nèi)分別執(zhí)行后續(xù)的計算操作。
1.2 數(shù)據(jù)切分的價值
- 并行計算:不同分片可以并行處理,提高查詢效率
- 邏輯清晰:將復(fù)雜查詢分解為多個獨立計算單元
- 結(jié)果可控:可以限制返回的分片數(shù)量,控制結(jié)果規(guī)模
二、PARTITION BY子句
2.1 語法結(jié)構(gòu)
PARTITION BY part_list
part_list可以是任意的標(biāo)量表達式,包括:
- 列名
- 常量
- 標(biāo)量函數(shù)
- 它們的組合
2.2 處理流程
TDengine按如下方式處理數(shù)據(jù)切分子句:
- 數(shù)據(jù)切分子句位于WHERE子句之后
- 數(shù)據(jù)切分子句將表數(shù)據(jù)按指定的維度進行切分,每個切分的分片進行指定的計算
- 計算由之后的子句定義(窗口子句、GROUP BY子句或SELECT子句)
- 數(shù)據(jù)切分子句可以和窗口切分子句(或GROUP BY子句)一起使用,此時后面的子句作用在每個切分的分片上
2.3 基本示例
按標(biāo)簽切分?jǐn)?shù)據(jù):
SELECT location, avg(voltage)
FROM meters
PARTITION BY location;
查詢結(jié)果:
location | avg(voltage) |
======================================================
California.SantaClara | 243.962050000000005 |
California.SanFrancisco | 243.962050000000005 |
California.SanJose | 243.962050000000005 |
California.LosAngles | 243.962050000000005 |
California.SanDiego | 243.962050000000005 |
California.Sunnyvale | 243.962050000000005 |
California.PaloAlto | 243.962050000000005 |
California.Cupertino | 243.962050000000005 |
California.MountainView | 243.962050000000005 |
California.Campbell | 243.962050000000005 |
Query OK, 10 row(s) in set (2.415961s)
三、PARTITION BY與窗口查詢結(jié)合
3.1 組合使用場景
當(dāng)需要對每個設(shè)備分別進行時間窗口聚合時,可以將PARTITION BY與窗口子句結(jié)合使用。
3.2 完整示例
SELECT tbname, _wstart, _wend, avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
AND ts < "2022-01-01T00:05:00+08:00"
PARTITION BY tbname
INTERVAL(1m, 5s)
SLIMIT 2;
這條SQL的執(zhí)行流程:
- WHERE過濾:篩選指定時間范圍的數(shù)據(jù)
- PARTITION BY切分:按子表名(tbname)切分?jǐn)?shù)據(jù)
- INTERVAL窗口:在每個分片內(nèi)按1分鐘窗口聚合
- SLIMIT限制:只返回前2個分片的結(jié)果
查詢結(jié)果:
tbname | _wstart | _wend | avg(voltage) |
======================================================================================
d2 | 2021-12-31 23:59:05.000 | 2022-01-01 00:00:05.000 | 253.000000000000000 |
d2 | 2022-01-01 00:00:05.000 | 2022-01-01 00:01:05.000 | 244.166666666666657 |
d2 | 2022-01-01 00:01:05.000 | 2022-01-01 00:02:05.000 | 241.833333333333343 |
d2 | 2022-01-01 00:02:05.000 | 2022-01-01 00:03:05.000 | 243.166666666666657 |
d2 | 2022-01-01 00:03:05.000 | 2022-01-01 00:04:05.000 | 240.833333333333343 |
d2 | 2022-01-01 00:04:05.000 | 2022-01-01 00:05:05.000 | 244.800000000000011 |
d26 | 2021-12-31 23:59:05.000 | 2022-01-01 00:00:05.000 | 253.000000000000000 |
d26 | 2022-01-01 00:00:05.000 | 2022-01-01 00:01:05.000 | 244.166666666666657 |
d26 | 2022-01-01 00:01:05.000 | 2022-01-01 00:02:05.000 | 241.833333333333343 |
d26 | 2022-01-01 00:02:05.000 | 2022-01-01 00:03:05.000 | 243.166666666666657 |
d26 | 2022-01-01 00:03:05.000 | 2022-01-01 00:04:05.000 | 240.833333333333343 |
d26 | 2022-01-01 00:04:05.000 | 2022-01-01 00:05:05.000 | 244.800000000000011 |
Query OK, 12 row(s) in set (0.021265s)
四、SLIMIT與SOFFSET
4.1 SLIMIT子句
SLIMIT用于限制返回的分片數(shù)量:
-- 只返回前1個分片
SELECT tbname, avg(voltage)
FROM meters
PARTITION BY tbname
SLIMIT 1;
4.2 SOFFSET子句
SOFFSET用于指定跳過的分片數(shù)量:
-- 跳過前5個分片,返回接下來的3個分片
SELECT tbname, avg(voltage)
FROM meters
PARTITION BY tbname
SLIMIT 3 SOFFSET 5;
4.3 分頁查詢
結(jié)合SLIMIT和SOFFSET實現(xiàn)分片分頁:
-- 第一頁
SELECT tbname, avg(voltage)
FROM meters
PARTITION BY tbname
SLIMIT 10 SOFFSET 0;
-- 第二頁
SELECT tbname, avg(voltage)
FROM meters
PARTITION BY tbname
SLIMIT 10 SOFFSET 10;
五、常用切分維度
5.1 按子表名切分
最常用的切分方式,按設(shè)備分片:
SELECT tbname, COUNT(*), AVG(voltage)
FROM meters
WHERE ts >= '2022-01-01 00:00:00'
PARTITION BY tbname;
5.2 按標(biāo)簽切分
按標(biāo)簽值進行分組:
SELECT location, COUNT(*), AVG(voltage)
FROM meters
WHERE ts >= '2022-01-01 00:00:00'
PARTITION BY location;
5.3 按表達式切分
支持使用表達式作為切分依據(jù):
-- 按分組ID模3切分
SELECT group_id % 3 as grp, AVG(voltage)
FROM meters
PARTITION BY group_id % 3;
六、PARTITION BY與GROUP BY的區(qū)別
| 特性 | PARTITION BY | GROUP BY |
|---|---|---|
| 作用位置 | WHERE之后 | 窗口子句之后 |
| 與窗口子句 | 可以一起使用 | 不能一起使用 |
| 計算方式 | 每個分片獨立計算 | 全局聚合 |
| 結(jié)果形式 | 多個分片的結(jié)果集 | 單一聚合結(jié)果 |
6.1 GROUP BY示例
SELECT groupid, avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
GROUP BY groupid;
6.2 PARTITION BY示例
SELECT tbname, avg(voltage)
FROM meters
WHERE ts >= "2022-01-01T00:00:00+08:00"
PARTITION BY tbname;
七、高級應(yīng)用場景
7.1 設(shè)備級時間窗口分析
對每個設(shè)備分別進行時間窗口聚合:
SELECT tbname, _wstart, avg(voltage), max(voltage), min(voltage)
FROM meters
WHERE ts >= '2022-01-01 00:00:00' AND ts < '2022-01-02 00:00:00'
PARTITION BY tbname
INTERVAL(1h)
SLIMIT 10;
7.2 地區(qū)分組統(tǒng)計
按地區(qū)分組進行統(tǒng)計:
SELECT location,
COUNT(*) as device_count,
AVG(voltage) as avg_voltage,
MAX(voltage) as max_voltage
FROM meters
PARTITION BY location;
7.3 多維度切分
支持多表達式切分:
SELECT location, group_id, AVG(voltage)
FROM meters
PARTITION BY location, group_id;
八、性能優(yōu)化建議
8.1 合理選擇切分維度
- 選擇區(qū)分度高的列作為切分維度
- 避免切分后分片數(shù)量過多
- 標(biāo)簽列是理想的切分維度
8.2 使用SLIMIT控制結(jié)果
- 大規(guī)模數(shù)據(jù)查詢時使用SLIMIT限制分片數(shù)量
- 結(jié)合SOFFSET實現(xiàn)分頁
- 避免一次性返回過多數(shù)據(jù)
8.3 配合時間范圍過濾
- 在WHERE子句中指定時間范圍
- 減少每個分片的數(shù)據(jù)量
- 提高查詢效率
九、注意事項
9.1 子句順序
正確的子句順序:
SELECT ...
FROM ...
WHERE ...
PARTITION BY ...
[窗口子句]
[SLIMIT ...]
9.2 與GROUP BY的限制
- PARTITION BY不能與GROUP BY同時使用
- 根據(jù)需求選擇合適的分組方式
9.3 結(jié)果排序
PARTITION BY不保證結(jié)果順序,如需排序應(yīng)使用ORDER BY:
SELECT tbname, avg(voltage)
FROM meters
PARTITION BY tbname
ORDER BY tbname;
總結(jié)
數(shù)據(jù)切分查詢是TDengine時序數(shù)據(jù)庫的重要特性,通過PARTITION BY子句,開發(fā)者可以靈活地按維度對數(shù)據(jù)進行切分,實現(xiàn)并行計算和精細化分析。結(jié)合窗口子句和SLIMIT限制,可以構(gòu)建強大的時序數(shù)據(jù)分析查詢。這種技術(shù)特別適用于物聯(lián)網(wǎng)和工業(yè)場景,能夠高效處理海量設(shè)備數(shù)據(jù),為工業(yè)數(shù)據(jù)管理平臺(IDMP)和實時數(shù)據(jù)庫應(yīng)用提供靈活的數(shù)據(jù)分析能力。TDengine憑借其完善的數(shù)據(jù)切分查詢功能,成為大規(guī)模時序數(shù)據(jù)分析的理想選擇。



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



-1.png)










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



