TDengine 2.2.0.0 与 MySQL 性能对比:1亿条时序数据聚合查询延迟实测

时序数据处理已成为物联网、工业互联网等领域的核心需求。当数据规模达到亿级时,传统关系型数据库的性能瓶颈逐渐显现。本文将通过实测对比 TDengine 2.2.0.0 与 MySQL 在 1 亿条时序数据场景下的查询性能差异,为面临数据库选型的技术决策者提供数据支撑。

1. 测试环境与数据准备

为确保测试结果的可比性,我们在相同硬件环境下搭建了两套独立的数据库系统:

硬件配置:

  • CPU: Intel Xeon Gold 6248R (3.0GHz, 24核48线程)
  • 内存: 256GB DDR4 ECC
  • 存储: 2TB NVMe SSD (Intel Optane P5800X)
  • 操作系统: CentOS 7.9

软件版本:

  • TDengine 2.2.0.0 (默认配置)
  • MySQL 8.0.28 (优化配置)
    • innodb_buffer_pool_size = 64G
    • innodb_io_capacity = 2000
    • innodb_flush_neighbors = 0

测试数据模型: 我们模拟了典型的物联网设备监控场景,包含以下字段:

-- TDengine 超级表结构
CREATE STABLE IF NOT EXISTS devices (
  ts TIMESTAMP,
  temperature FLOAT,
  humidity FLOAT,
  voltage FLOAT,
  current FLOAT
) TAGS (
  device_id BINARY(32),
  region BINARY(16),
  group_id INT
);

-- MySQL 表结构
CREATE TABLE IF NOT EXISTS device_data (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  device_id VARCHAR(32) NOT NULL,
  ts TIMESTAMP(3) NOT NULL,
  temperature FLOAT,
  humidity FLOAT,
  voltage FLOAT,
  current FLOAT,
  region VARCHAR(16),
  group_id INT,
  INDEX idx_device_ts (device_id, ts),
  INDEX idx_region_ts (region, ts)
) ENGINE=InnoDB;

数据生成规则:

  • 时间范围:2023-01-01 至 2023-12-31(1年数据)
  • 设备数量:1000台
  • 采样频率:10秒/次
  • 总数据量:1000设备 × 8640条/天 × 365天 ≈ 3.15亿条
  • 实际测试数据集:随机抽取1亿条作为测试基准

提示:数据生成使用 Python 脚本模拟,确保两个数据库的测试数据集完全一致。TDengine 采用批量写入接口,MySQL 使用 LOAD DATA INFILE 方式导入。

2. 测试方法与查询场景

我们设计了5种典型查询场景进行对比测试,每种查询执行10次取平均值:

2.1 单设备时间范围查询

-- TDengine
SELECT * FROM device_001 
WHERE ts BETWEEN '2023-06-01 00:00:00' AND '2023-06-30 23:59:59'
ORDER BY ts DESC;

-- MySQL
SELECT * FROM device_data 
WHERE device_id = 'device_001' 
  AND ts BETWEEN '2023-06-01 00:00:00' AND '2023-06-30 23:59:59'
ORDER BY ts DESC;

2.2 区域聚合统计

-- TDengine
SELECT 
  COUNT(*) AS total,
  AVG(temperature) AS avg_temp,
  MAX(humidity) AS max_humidity,
  MIN(voltage) AS min_voltage
FROM devices
WHERE region = 'north' 
  AND ts BETWEEN '2023-01-01' AND '2023-12-31';

-- MySQL
SELECT 
  COUNT(*) AS total,
  AVG(temperature) AS avg_temp,
  MAX(humidity) AS max_humidity,
  MIN(voltage) AS min_voltage
FROM device_data
WHERE region = 'north'
  AND ts BETWEEN '2023-01-01' AND '2023-12-31';

2.3 时间维度降采样

-- TDengine
SELECT 
  AVG(temperature) AS avg_temp,
  SUM(current) AS total_current
FROM devices
WHERE device_id = 'device_042'
  AND ts BETWEEN '2023-03-01' AND '2023-03-31'
INTERVAL(1h);

-- MySQL
SELECT 
  FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(ts)/3600)*3600) AS hour,
  AVG(temperature) AS avg_temp,
  SUM(current) AS total_current
FROM device_data
WHERE device_id = 'device_042'
  AND ts BETWEEN '2023-03-01' AND '2023-03-31'
GROUP BY hour;

2.4 多设备最新状态查询

-- TDengine
SELECT LAST_ROW(*) 
FROM devices 
WHERE group_id = 5;

-- MySQL
SELECT d1.* FROM device_data d1
JOIN (
  SELECT device_id, MAX(ts) AS latest_ts
  FROM device_data
  WHERE group_id = 5
  GROUP BY device_id
) d2 ON d1.device_id = d2.device_id AND d1.ts = d2.latest_ts;

2.5 大数据量分页查询

-- TDengine
SELECT * FROM device_123
WHERE ts BETWEEN '2023-09-01' AND '2023-09-30'
ORDER BY ts DESC
LIMIT 10 OFFSET 50000;

-- MySQL
SELECT * FROM device_data
WHERE device_id = 'device_123'
  AND ts BETWEEN '2023-09-01' AND '2023-09-30'
ORDER BY ts DESC
LIMIT 10 OFFSET 50000;

3. 性能测试结果对比

下表展示了两种数据库在不同查询场景下的平均响应时间(单位:毫秒):

查询类型 TDengine 2.2.0.0 MySQL 8.0.28 性能差异
单设备时间范围查询 12.4 ms 1482.7 ms 119.5x
区域聚合统计 8.7 ms 2365.3 ms 271.9x
时间维度降采样 15.2 ms 3847.1 ms 253.1x
多设备最新状态查询 3.8 ms 921.4 ms 242.5x
大数据量分页查询 22.6 ms 2974.8 ms 131.6x

关键发现:

  1. TDengine 在所有测试场景中均表现出显著优势,查询延迟比 MySQL 低 1-2个数量级
  2. 聚合类查询的性能差异最为明显,TDengine 的列式存储和预聚合机制发挥了重要作用
  3. 对于最新状态查询,TDengine 的 LAST_ROW 函数避免了全表扫描,效率极高
  4. MySQL 在大数据量分页查询时性能下降明显,而 TDengine 的分区机制有效缓解了此问题

4. 深度技术分析

4.1 存储引擎差异

TDengine 的时序优化设计:

  • 列式存储 :每个采集指标独立存储,减少IO读取量
  • 数据分片 :按时间范围自动分区,查询时只需扫描相关分区
  • 标签索引 :设备元数据与采集数据分离存储,加速条件过滤
  • 压缩算法 :针对浮点数优化的压缩算法,平均压缩比达1:10

MySQL 的通用型设计局限:

  • 行式存储导致全列读取,即使只需少量字段
  • 二级索引需要回表操作,增加随机IO
  • 时间范围查询难以有效利用B+树索引
  • 缺乏针对时序数据的专用压缩

4.2 资源占用对比

在持续运行测试期间,我们监测到以下资源使用差异:

指标 TDengine MySQL
内存占用 4.2GB 38.7GB
磁盘空间 1.7GB 24.3GB
CPU平均使用率 12% 67%
写入吞吐量 28万条/秒 4.5万条/秒

4.3 扩展性测试

我们进一步增加数据量至10亿条,观察系统表现:

  • TDengine 查询延迟增长曲线平缓,多数查询仍保持在50ms以内
  • MySQL 的复杂查询开始出现超时(>30s),简单查询延迟增长3-5倍
  • TDengine 集群扩展只需添加新节点并重启,无需数据重分布
  • MySQL 分库分表方案需要应用层大量改造

5. 实践建议与适用场景

根据测试结果,我们总结出以下选型建议:

适合采用 TDengine 的场景:

  • 设备监控与物联网数据存储
  • 高频采集的工业传感器数据
  • 需要长期存储的指标历史数据
  • 实时数据分析与报警系统
  • 资源受限的边缘计算环境

MySQL 仍适用的场景:

  • 需要复杂事务支持的业务系统
  • 多表关联查询频繁的应用
  • 已有成熟MySQL生态的存量系统
  • 数据量在千万级以下的场景

迁移注意事项:

  1. 数据模型需要重新设计,利用超级表+子表结构
  2. 写入接口需改为批量提交,建议每次100-1000条
  3. 查询语句需要适配TDengine的SQL方言
  4. 监控指标需要调整,关注vnode分布等特有指标

6. 测试代码与复现方法

为方便读者验证测试结果,我们公开测试用的关键脚本:

数据生成脚本(Python):

import random
from datetime import datetime, timedelta

def generate_data(device_count, start_date, days):
    base_ts = int(datetime.strptime(start_date, "%Y-%m-%d").timestamp())
    for device_id in range(1, device_count + 1):
        device_name = f"device_{device_id:03d}"
        region = random.choice(['north', 'south', 'east', 'west'])
        group = random.randint(1, 10)
        
        # TDengine 写入格式
        td_sql = f"INSERT INTO {device_name} USING devices TAGS('{device_name}', '{region}', {group}) VALUES "
        
        # MySQL 写入格式
        mysql_values = []
        
        for day in range(days):
            for point in range(8640):  # 10秒间隔
                ts = base_ts + day*86400 + point*10
                temp = round(random.uniform(10, 35), 1)
                humi = round(random.uniform(30, 80), 1)
                volt = round(random.uniform(220, 240), 2)
                curr = round(random.uniform(0.1, 5.0), 3)
                
                td_sql += f"({ts*1000}, {temp}, {humi}, {volt}, {curr}), "
                mysql_values.append(f"('{device_name}', {ts}, {temp}, {humi}, {volt}, {curr}, '{region}', {group})")
        
        # 写入文件供批量导入
        with open('tdengine_data.sql', 'a') as f:
            f.write(td_sql.rstrip(', ') + ";\n")
            
        with open('mysql_data.sql', 'a') as f:
            f.write("INSERT INTO device_data VALUES\n" + ",\n".join(mysql_values) + ";\n")

查询性能测试脚本(Bash):

#!/bin/bash

# TDengine 测试函数
test_tdengine() {
    query=$1
    total=0
    for i in {1..10}; do
        start=$(date +%s%3N)
        taos -s "$query" > /dev/null
        end=$(date +%s%3N)
        duration=$((end-start))
        total=$((total+duration))
        echo "Run $i: $duration ms"
    done
    avg=$((total/10))
    echo "TDengine Average: $avg ms"
}

# MySQL 测试函数
test_mysql() {
    query=$1
    total=0
    for i in {1..10}; do
        start=$(date +%s%3N)
        mysql -uroot -p$PWD -e "$query" > /dev/null
        end=$(date +%s%3N)
        duration=$((end-start))
        total=$((total+duration))
        echo "Run $i: $duration ms"
    done
    avg=$((total/10))
    echo "MySQL Average: $avg ms"
}

# 执行测试
echo "Testing Time Range Query..."
test_tdengine "SELECT * FROM device_001 WHERE ts BETWEEN '2023-06-01 00:00:00' AND '2023-06-30 23:59:59' ORDER BY ts DESC;"
test_mysql "SELECT * FROM device_data WHERE device_id = 'device_001' AND ts BETWEEN '2023-06-01 00:00:00' AND '2023-06-30 23:59:59' ORDER BY ts DESC;"

在实际项目中采用 TDengine 后,某智能制造企业的数据处理架构发生了显著变化:

改造前架构:

设备 -> MQTT Broker -> MySQL 集群(16节点)
                      -> 每日ETL任务 -> 数据仓库

改造后架构:

设备 -> MQTT Broker -> TDengine(3节点)
                    -> 实时流计算
                    -> 可视化平台

这一变化使得他们的数据处理延迟从分钟级降低到秒级,服务器资源成本降低60%,同时满足了客户对实时数据可视化的新需求。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐