分类9.索引 |篇章02 SMA 索引适用版本TDengine v3.xv3.3.x / v3.4.x | 最后更新2026-06-04SMASmall Materialized Aggregation是 TDengine 在数据块/文件级别自动维护的统计索引。它不像传统 B-Tree 索引而是为聚合查询和过滤剪枝服务。本文聚焦SMA 作为索引的视角。核心概念速查表概念说明Block SMA数据块统计min/max/sum/countFile SMA数据文件统计Skipping Index跳过索引基于范围Bloom Filter布隆过滤视版本Index Effectiveness索引有效性详细解析1. SMA 索引的定位传统索引B-Treevs SMA 索引 B-Tree 索引Tag 索引 - 行级精确定位 - 适合等值/范围查询 - 占空间大 SMA 索引 - 块级统计跳过 - 适合聚合 大范围过滤 - 占空间极小 1% - 时序数据场景优势明显 定位 - Tag 索引跨子表筛选 - SMA 索引单子表内的块剪枝2. Block SMA 工作原理每个数据块 4096 行存储元数据 Block Header { time_range: [ts_min, ts_max], row_count: 4096, cols: [ { name: current, min: 20.5, max: 25.8, sum: 95000, count: 4096 }, { name: voltage, min: 218, max: 223, sum: 902160, count: 4096 }, { name: phase, min: 0.45, max: 0.55, sum: 2048, count: 4096 }, ] } 查询时的判断 SELECT * FROM d001 WHERE current 100 AND ts T1; 对每个块 if block.time_range.max T1: 跳过 if block.cols.current.max 100: 跳过 else: 进入块读取3. SMA 用于聚合优化SELECT AVG(current) FROM d001 WHERE ts T1; 执行 ① 找到符合时间范围的所有块 ② 对每个块 - 直接读取 SMA 中的 sum 和 count - 不解码原始数据 ③ 累加total_sum / total_count 效果 - 100 万行数据扫描 ~250 个块 - 仅读块 Header~50KB - 不读 .data 主体数 GB - 毫秒返回 支持函数 ✓ COUNT, SUM, AVG需 sum/count ✓ MIN, MAX ✓ FIRST, LAST部分场景 ✗ PERCENTILE, MEDIAN需扫行4. SMA 用于过滤剪枝WHERE 子句的剪枝 WHERE current 100 对每个块 if block.cols.current.max 100: 整块跳过 if block.cols.current.min 100: 整块满足可能加速 else: 块部分匹配需扫描行 示例 100 万行分 250 个块 WHERE current 100 - 200 块 max 100 → 跳过 - 30 块 min 100 → 全选 - 20 块部分匹配 → 扫描行 实际扫描行数20 × 4096 82K节省 92%5. 时间维度的 SMA时间列是隐式 SMA 关键 每块的 time_range 用于时间裁剪 WHERE ts T → 跳过所有 ts_max T 的块 WHERE ts BETWEEN T1 AND T2 → 跳过范围外 时间裁剪是最有效的剪枝时序数据按时间分布 三级裁剪 ① 文件级跳过整个 .data 文件 ② 块级跳过文件内部分块 ③ 行级块内进一步过滤按数据列6. SMA 索引效果监控-- EXPLAIN ANALYZE 看实际效果EXPLAINANALYZESELECTAVG(current)FROMmetersWHEREtsnow-1hANDvoltage200;-- 关键指标-- blocks_total: 总块数-- blocks_scanned: 实际扫描的块数-- blocks_skipped: 跳过的块数SMA 生效-- rows_examined: 实际读取行数-- rows_returned: 返回行数-- 比率 blocks_skipped / blocks_total-- 高比率说明 SMA 有效7. 影响 SMA 索引效果的因素影响因素 ① 块大小MAXROWS - 小块更细粒度剪枝但块多 - 大块单块容纳更多数据剪枝粒度粗 - 默认 4096 通常合适 ② 数据分布 - 同块内数据相似 → 剪枝效果好 - 同块内数据差异大 → 剪枝难 ③ 列类型 - 数值类型剪枝有效 - 字符串类型 SMA 较弱 ④ 数据排序 - 按 ts 自然排序 → 时间剪枝最优 - 数据列乱序 → 数据列剪枝弱8. SMA 索引设计建议最佳实践 ① 让常查询列与时间有相关性 - 时间相近的数据值也相近 → 块内 min/max 紧凑 - 利于过滤剪枝 ② 控制块大小 - 默认 MAXROWS 4096 适合大多数场景 - 极少行/极多行可能需调整 ③ 不要过度依赖 SMA - 复杂表达式无法用 SMA - 字符串 LIKE 等无 SMA ④ 配合 Tag 索引 - Tag 索引筛选子表 - SMA 索引剪枝块 - 两者协同最强代码示例SMA 效果验证-- 准备数据INSERTINTOd001USINGmeters TAGS(Beijing,1)VALUES(NOW-1d,25,220,0.5);-- ... 写入百万行-- 测试 1: 时间范围SMA 最有效EXPLAINANALYZESELECTCOUNT(*)FROMd001WHEREtsnow-1h;-- 期望 blocks_skipped 大-- 测试 2: 数据列过滤EXPLAINANALYZESELECTCOUNT(*)FROMd001WHEREcurrent100;-- 期望部分 blocks_skipped取决于数据分布-- 测试 3: 聚合SMA 直接命中EXPLAINANALYZESELECTAVG(current)FROMd001WHEREtsnow-1d;-- 期望 rows_examined 几乎为 0直接用 SMA sum/count提升 SMA 命中-- ✗ 复杂过滤无法用 SMASELECT*FROMmetersWHEREcurrentAVG(current);-- ✓ 简单常量比较SELECT*FROMmetersWHEREcurrent100;-- ✗ 函数包裹SELECT*FROMmetersWHEREABS(phase-0.5)0.1;-- ✓ 直接范围SELECT*FROMmetersWHEREphaseBETWEEN0.4AND0.6;性能考量SMA 索引性能特点场景SMA 效果时间裁剪极高90% 跳过数值列过滤中~高取决于分布聚合 SUM/AVG/COUNT极高直接读 SMAMIN/MAX极高直接读 SMA字符串过滤低复杂表达式无效存储开销项占比块 SMA 1%文件 SMA 0.1%TSMA/RSMA1%~10%Tag 索引 0.1%FAQQ1: SMA 索引可以手动创建吗块/文件 SMA 自动维护。TSMA/RSMA 需要 CREATE TSMA 或建库 RETENTIONS。Q2: SMA 索引会失效吗写入新数据 → 新块自动有 SMA。Compaction 重算 SMA。极端故障 数据修复后 SMA 自动重建。Q3: 字符串列 SMA 弱怎么办转为枚举Tag用前缀提取列或接受较低性能Q4: 如何判断 SMA 是否生效EXPLAIN ANALYZE 看 blocks_skipped。比率 80% 说明有效。Q5: 不同版本 SMA 行为差异总体方向一致。新版本可能增加 Bloom Filter、字符串 min/max 等。具体看版本 Release Note。参考系统构架篇01-《TDengine 整体架构全景》02-《集群拓扑深度解析》03-《MNode 内部机制深度解析》04-《RPC 通信层深度解析》05-《VNode 生命周期》06-《RAFT 共识协议》07-《端到端的消息流》数据模型01-《数据库创建与参数详解》02-《超级表/子表/普通表》03-《支持数据类型深度解析》04-《TDengine Tag 设计哲学与 Schema 变更机制》05-《TDengine 虚拟表实现原理》存储引擎01-《TDengine 存储引擎概览》02-《TDengine MemTable 深度解析》03-《TDengine WAL 预写日志机制》04-《TDengine 数据文件格式》05-《TDengine Commit 与 Flush 机制 》06-《TDengine Compaction 合并策略 》07-《TDengine 数据保留与 TTL》08-《TDengine 压缩编码机制》09-《TDengine Cache 与 Last 查询加速》10-《TDengine 逻辑计划生成》查询引擎01-《TDengine 查询引擎概览》02-《TDengine SQL 解析与词法分析》03-《TDengine 语义分析与 AST 重写》04-《TDengine 逻辑计划生成》05-《TDengine 物理计划生成》06-《TDengine 扫描算子》07-《TDengine 聚合算子》08-《TDengine 聚合算子》09-《TDengine 连接算子》10-《TDengine 排序、填充与投影》11-《TDengine 分布式查询执行》12-《TDengine EXPLAIN 与查询优化》数据写入01-《TDengine SQL INSERT》02-《TDengine 无模式写入》03-《TDengine STMT 写入》04-《TDengine 写入内部流程》05-《TDengine 数据更新删除》数据订阅01-《TDengine 数据订阅》02-《TDengine 订阅 vs Kafka》03-《TDengine TMQ 消费流程》04-《TDengine 内部机制》05-《TDengine TMQ 最佳实践》预聚合01-《TDengine RSMA》02-《TDengine TSMA — 时间维度的物化聚合视图》03-《TDengine SMA 内部实现》索引01-《TDengine Tag 索引》关于 TDengineTDengine 专为物联网IoT平台、工业大数据平台设计。其中TDengine TSDB 是一款高性能、分布式的时序数据库Time Series Database同时它还带有内建的缓存、流式计算、数据订阅等系统功能TDengine IDMP 是一款AI原生工业数据管理平台它通过树状层次结构建立数据目录对数据进行标准化、情景化并通过 AI 提供实时分析、可视化、事件管理与报警等功能。