分类:4.查询引擎 | 篇章:01 查询引擎概览

在这里插入图片描述

适用版本:TDengine v3.x(v3.3.x / v3.4.x) | 最后更新:2026-06-07

TDengine 的查询引擎是一套面向时序数据特征定制的分布式 SQL 执行框架。它从客户端解析 SQL 开始,经过语义分析、逻辑/物理计划生成、任务下发、算子并行执行、最终结果汇总,全过程围绕"按时间分片+按子表并行+按列裁剪"的核心理念展开。

核心概念速查表

概念 说明
Parser 将 SQL 文本转为抽象语法树(AST)
Translator 语义分析、Catalog 校验、AST 重写
Logical Plan 与执行引擎无关的关系代数表达
Physical Plan 落地到具体算子的可执行计划
Scheduler 任务调度器,决定子查询发到哪个节点
QNode 专用查询节点(可选,分担 VNode 计算压力)
Operator 执行算子(Scan/Filter/Aggregate/Join/Sort/…)
DataSink 数据汇聚通道(连接算子间或节点间)

详细解析

1. 查询整体架构

查询执行的端到端流程:

  ┌─────────────────────────────────────────────────────┐
  │                  Client (libtaos)                    │
  │  ① Parser → ② Translator → ③ Planner → ④ Scheduler   │
  └────────────────────────┬────────────────────────────┘
                           │ RPC 下发任务
        ┌──────────────────┼──────────────────┐
        ▼                  ▼                  ▼
  ┌──────────┐      ┌──────────┐       ┌──────────┐
  │  VNode 1 │      │  VNode 2 │       │  QNode   │
  │  执行扫描 │      │  执行扫描 │  ←─→  │ 汇总聚合 │
  │  本地聚合 │      │  本地聚合 │       │ 排序合并 │
  └──────────┘      └──────────┘       └──────────┘
        │                  │                  │
        └──────────────────┴──────────────────┘
                           │ 结果回传
                           ▼
                  ┌──────────────────┐
                  │     Client        │
                  │   收集 + 输出      │
                  └──────────────────┘

2. 客户端处理阶段

SQL 在客户端的完整生命周期:

  SQL 字符串
      │
      ▼
  ① Tokenizer(词法分析)
     拆分为 Token 序列:SELECT, *, FROM, meters, WHERE, ts, >, '...'
      │
      ▼
  ② Parser(Lemon 生成的 LALR 语法分析器)
     构建 AST(抽象语法树):
        SelectStmt
        ├── projection: [*]
        ├── from: meters
        └── where: ts > '...'
      │
      ▼
  ③ Translator(语义分析)
     - 查 Catalog 校验表/列是否存在
     - 列名/类型绑定
     - Tag 过滤下推到 Catalog 层(仅相关子表参与)
     - 重写 AST(如展开 *、补默认窗口等)
      │
      ▼
  ④ Logical Planner
     生成逻辑算子树:
        Project
          └── Filter (ts > '...')
                └── Scan (meters)
      │
      ▼
  ⑤ Physical Planner
     - 分解为多个 SubPlan(按 VGroup 切分)
     - 每个 SubPlan 包含物理算子链
     - 决定 Exchange 数据流方向
      │
      ▼
  ⑥ Scheduler
     将 SubPlan 下发到对应节点(VNode/QNode)

3. 服务端执行阶段

服务端算子执行模型(Pull-based + Pipeline):

  ┌──────────────────────────────────────────────────────┐
  │  Result Operator(结果输出)                          │
  │     │  getNextBlock()                                 │
  │     ▼                                                  │
  │  Aggregate Operator                                  │
  │     │  getNextBlock()                                 │
  │     ▼                                                  │
  │  Filter Operator                                     │
  │     │  getNextBlock()                                 │
  │     ▼                                                  │
  │  Scan Operator(读 MemTable + STT + .data)          │
  └──────────────────────────────────────────────────────┘

  特点:
  - Pull 模型:上层算子驱动下层算子产出数据
  - 列式 DataBlock 在算子间流转(不是行流)
  - 一次产出一个 Block(默认 4096 行)
  - 算子无状态时可并行(多线程同时跑多个 Scan)

4. 数据传输:Exchange 与 DataSink

节点间的数据流:

  VNode 1 Scan      VNode 2 Scan      VNode 3 Scan
       │                │                  │
       ▼                ▼                  ▼
  DataSink:           DataSink:         DataSink:
  ShuffleDispatch    ShuffleDispatch    ShuffleDispatch
       │                │                  │
       └──────────┬─────┴──────────────────┘
                  ▼
         ┌─────────────────┐
         │ Exchange Operator│  ← QNode 或 Client 端
         │   (按需 Fetch)   │
         └────────┬────────┘
                  ▼
            Aggregate / Sort

5. 时序场景的查询优化点

优化 说明
时间裁剪 WHERE 含时间条件 → 仅扫描相关 File Set
Tag 索引 WHERE Tag 条件 → META 索引返回 uid 列表,跳过无关子表
块级 SMA COUNT/MIN/MAX/SUM 直接读预聚合,免解压
列裁剪 SELECT 中未引用的列不解压、不读取
并行扫描 多 VGroup 并行,多子表并行
本地预聚合 VNode 内先聚合再 Exchange,减少网络传输

6. QNode 与 VNode 的协作

QNode 的引入:

  传统模式(VNode 既存储又计算):
    SELECT COUNT(*) FROM big_table GROUP BY tbname
    → 全部计算压在 VNode,CPU 与写入竞争资源
  
  引入 QNode:
    Scan 在 VNode 完成(必须,靠近存储)
    复杂计算(大规模 Sort/Hash Aggregate/Join)转到 QNode
    → 写入与查询解耦
    → 可独立扩展查询能力
  
  调度规则(简化):
    - 简单聚合 → VNode 本地完成
    - 跨 VGroup 合并 → QNode 或 Client
    - 显式 USE_QNODE hint → 强制 QNode

7. 查询的并发与隔离

查询的并发模型:

  ┌────────────────────────────────────────┐
  │  taosd 进程                              │
  │                                          │
  │  查询线程池(vnodeQueryQueue)            │
  │  ├── worker 1 → 处理 Query Task          │
  │  ├── worker 2 → 处理 Query Task          │
  │  └── worker N → 处理 Query Task          │
  │                                          │
  │  并发隔离:                                │
  │  - 查询不阻塞写入(独立线程池)            │
  │  - 长查询不影响短查询(按 Task 调度)     │
  │  - 内存配额限制单查询占用                  │
  └────────────────────────────────────────┘

代码示例

观察查询执行计划

-- 查看查询计划
EXPLAIN SELECT avg(current) FROM meters WHERE ts > now - 1h;

-- 查看详细执行统计
EXPLAIN ANALYZE SELECT avg(current) FROM meters WHERE ts > now - 1h;

-- 查看慢查询
SELECT * FROM performance_schema.perf_queries 
ORDER BY exec_usec DESC LIMIT 10;

配置查询资源

-- 查询线程数(taos.cfg)
-- numOfVnodeQueryThreads 8

-- 单查询内存上限
ALTER ALL DNODES 'queryBufferSize 10240';   -- MB

-- 启用 QNode
CREATE QNODE ON DNODE 3;
SHOW QNODES;

性能考量

影响查询性能的关键因素

因素 影响 建议
WHERE 时间范围 决定扫描 File Set 数 总是带时间条件
Tag 过滤选择性 决定参与子表数 高基数 Tag 优先
SELECT 列数 决定解压列数 只选需要的列
GROUP BY 基数 决定中间结果大小 避免在大基数 Tag 上 GROUP
并发查询数 决定线程争抢 通过 QNode 隔离重查询

典型查询延迟参考

查询类型 数据规模 延迟
LAST() 缓存命中 任意 < 1ms
单子表点查(带 ts) 1 天数据 1~10ms
单超级表聚合 1 万子表 × 1 小时 50~500ms
跨 VGroup GROUP BY 100 万子表 × 1 天 1~10s
大范围 JOIN 视数据量 秒~分钟级

FAQ

Q1: 为什么 SELECT * 比 SELECT col1 慢很多?

列式存储下每列独立压缩。SELECT * 需要解压所有列并重组为行。如果表有 100 列但只关心 1 列,可减少约 99% 的解压和 I/O。

Q2: WHERE 不带时间条件会怎样?

会扫描所有 File Set(可能数十到数百个文件)。在 TB 级数据上可能持续数分钟。生产环境务必带时间条件

Q3: QNode 是必须的吗?

不是必须。小集群可不部署 QNode,VNode 既存储又计算。当:

  • 查询并发高且影响写入
  • 集群有大量复杂分析查询
  • 希望独立扩展查询能力

建议部署 QNode。

Q4: 查询是按行还是按列执行?

按列。算子之间传递的是列式 DataBlock(每列一个独立数组)。这与 ClickHouse 等列式 OLAP 引擎类似,能高效利用 SIMD 和缓存。

参考

系统构架篇

数据模型

存储引擎

关于 TDengine

TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐