在支付风控、对账大盘、交易溯源这类强时序特征的业务里,很多团队会纠结选专用时序库 TDengine还是OLAP 宽表分析引擎 ClickHouse。二者底层设计、更新机制、查询优化、运维成本差异极大,本文以真实支付流水业务为载体,给出可直接落地的表结构、增改查 SQL、选型判断标准。

一、业务场景定义

业务需求

记录支付订单全生命周期时序快照,支持:

  • 高并发写入:大促峰值每秒上万条订单状态变更记录;
  • 多维查询:按时间、商户、渠道做分时交易额、成功率统计;
  • 状态更新:订单从待支付→支付成功→退款多次状态流转;
  • 合规溯源:永久保留每一次状态变更的完整轨迹;
  • 冷热分层:近 30 天热数据低延迟查询,超 90 天冷数据自动低成本归档。

核心字段约定

字段名

含义

类型说明

ts

事件时间戳(主键维度)

高精度时间

order_no

订单唯一号

字符串

merchant_id

商户 ID

整型

pay_channel

支付渠道(微信 / 支付宝)

标签维度

trade_status

订单状态:0 待支付 / 1 成功 / 2 失败 / 3 退款

枚举整型

trade_amount

交易金额

定点小数

refund_amount

退款金额

定点小数

callback_info

回调原始报文

长文本

二、TDengine 实现方案(专用时序数据库)

1. 表结构设计(TDengine 3.0 超级表模型)

TDengine 采用超级表 (STable)+ 子表模型,以设备 / 业务主体做分片,天然适配时序标签场景,这里以merchant_id作为子表分片键:

sql
-- 创建超级表:支付流水主超级表
CREATE STABLE pay_trade_stb (
    ts TIMESTAMP,
    order_no NCHAR(32),
    trade_status TINYINT,
    trade_amount DECIMAL(18,2),
    refund_amount DECIMAL(18,2),
    callback_info NCHAR(1024)
) TAGS (
    merchant_id INT,
    pay_channel NCHAR(16)
);

  • 超级表定义通用 Schema,TAGS里的merchant_idpay_channel作为分片和过滤标签;
  • 插入数据时 TDengine 自动按merchant_id创建子表,同商户数据物理聚合,查询裁剪效率极高;
  • 时间戳ts默认做主排序键,数据按时间连续落盘。

2. 写入(模拟状态更新:追加快照模式)

TDengine不推荐原地 UPDATE,最佳实践是状态变更就插入一条新时序快照:

sql
-- 1. 订单创建:初始状态写入(自动归属merchant_id=10001、渠道微信的子表)
INSERT INTO pay_trade_10001 USING pay_trade_stb TAGS(10001, 'WECHAT')
VALUES ('2026-09-01 10:00:00.123', 'PAY20260901001', 0, 99.00, 0.00, '下单回调初始化');

-- 2. 订单支付成功:追加新快照,不修改旧数据
INSERT INTO pay_trade_10001 USING pay_trade_stb TAGS(10001, 'WECHAT')
VALUES ('2026-09-01 10:00:05.456', 'PAY20260901001', 1, 99.00, 0.00, '微信支付成功回调');

-- 3. 订单全额退款:再追加一条快照
INSERT INTO pay_trade_10001 USING pay_trade_stb TAGS(10001, 'WECHAT')
VALUES ('2026-09-01 14:30:10.789', 'PAY20260901001', 3, 99.00, 99.00, '全额退款回调');

3. 高频查询实操

(1)查单个订单最新状态

sql
SELECT LAST(ts), LAST(trade_status), LAST(refund_amount)
FROM pay_trade_stb
WHERE order_no = 'PAY20260901001'
TAGS(merchant_id=10001);

(2)按小时统计商户当日交易额 & 成功率

sql
-- 2026-09-01 商户10001每小时交易总额、成功笔数
SELECT INTERVAL(ts, 1h), SUM(trade_amount), COUNT_IF(trade_status=1)
FROM pay_trade_stb
WHERE ts >= '2026-09-01 00:00:00' AND ts < '2026-09-02 00:00:00'
TAGS(merchant_id=10001)
GROUP BY INTERVAL(ts, 1h)
ORDER BY INTERVAL(ts, 1h);

4. 特殊更新场景处理

  • 业务状态流转:全程追加新快照,保留全量变更轨迹,符合金融审计要求;
  • 极少量错误修正:支持按ts+子表原地覆盖写入(同一子表同一时间戳插入新行会覆盖旧数据),不适合高频修改;
  • 逻辑删除:用软删除标签标记,或按 TTL 自动过期清理冷数据。

5. TDengine 适配优势

  • 标签分片天然隔离不同商户数据,多租户场景权限、性能隔离更简单;
  • 内置降采样、时间窗口函数,大盘统计 SQL 极简;
  • 自带冷热分层、数据 TTL,运维不用手动规划分区。

三、ClickHouse 实现方案(OLAP 分析引擎)

1. 表结构设计(MergeTree 引擎,适配时序分析)

采用最常用的MergeTree,排序键贴合查询前缀(ts, merchant_id, order_no),自动生成稀疏主键索引:

sql
CREATE TABLE pay_trade_ck (
    ts DateTime64(3),
    order_no String,
    merchant_id UInt32,
    pay_channel LowCardinality(String), -- 低基数字段压缩优化
    trade_status UInt8,
    trade_amount Decimal(18,2),
    refund_amount Decimal(18,2),
    callback_info String
) ENGINE = MergeTree()
PARTITION BY toDate(ts) -- 按天分区,快速裁剪时间范围
ORDER BY (ts, merchant_id, order_no) -- 排序键决定物理存储顺序
PRIMARY KEY (ts, merchant_id, order_no)
TTL ts + INTERVAL 90 DAY DELETE, -- 90天以上冷数据自动清理
SETTINGS index_granularity = 8192;

优化细节:

  • LowCardinality压缩渠道这类枚举标签,降低存储占用;
  • 按天分区 + 排序键前缀匹配,时间 + 商户过滤可以二分跳过大量数据块。

2. 写入(同样推荐追加快照模式)

sql
INSERT INTO pay_trade_ck VALUES
('2026-09-01 10:00:00.123', 'PAY20260901001', 10001, 'WECHAT', 0, 99.00, 0.00, '下单回调初始化'),
('2026-09-01 10:00:05.456', 'PAY20260901001', 10001, 'WECHAT', 1, 99.00, 0.00, '微信支付成功回调'),
('2026-09-01 14:30:10.789', 'PAY20260901001', 10001, 'WECHAT', 3, 99.00, 99.00, '全额退款回调');

如果只需要保留订单最新状态,可改用ReplacingMergeTree(ts),后台合并时按order_no保留时间戳最大的行:

sql
ENGINE = ReplacingMergeTree(ts)
ORDER BY (order_no);

3. 高频查询实操

(1)查单个订单最新状态

sql
SELECT
    argMax(trade_status, ts) AS latest_status,
    argMax(refund_amount, ts) AS latest_refund
FROM pay_trade_ck
WHERE order_no = 'PAY20260901001' AND merchant_id = 10001
GROUP BY order_no;

-- ReplacingMergeTree写法:FINAL直接取合并后最新数据
SELECT * FROM pay_trade_ck FINAL WHERE order_no = 'PAY20260901001';

(2)按小时统计商户分时数据

sql
SELECT
    toStartOfHour(ts) AS hour_time,
    sum(trade_amount) AS total_amount,
    countIf(trade_status = 1) AS success_cnt
FROM pay_trade_ck
WHERE ts >= '2026-09-01 00:00:00' AND ts < '2026-09-02 00:00:00'
  AND merchant_id = 10001
GROUP BY hour_time
ORDER BY hour_time;

4. 更新方案分级使用

  • 常规业务更新:永远追加新快照,用argMax取最新,写入性能零损耗;
  • 低频数据修正:用ALTER TABLE ... UPDATE(Mutation)异步重写数据块,仅限每月级别的脏数据修复;
  • 逻辑删除:轻量DELETE打标记,后台合并再物理清理。

5. ClickHouse 适配优势

  • 支持极宽表设计,可以轻松扩展上百个维度字段,适合复杂多维度经营分析;
  • SQL 语法和 MySQL 高度兼容,开发迁移成本低;
  • 向量化计算能力强,超大范围全量数据分析速度优势明显。

四、两大引擎核心维度横向对比

对比维度

TDengine 3.0

ClickHouse

数据模型

超级表 + 子表,标签原生分片,时序场景专属优化

宽表 MergeTree,通用 OLAP 列式模型

写入能力

高并发时序写入延迟极低,海量设备 / 商户场景优势拉满

批量写入极强,单行高频写入优化弱于 TDengine

更新机制

仅支持同时间戳覆盖,业务用追加快照

支持 Mutation 异步更新,严格限制高频使用

查询擅长场景

细粒度时序窗口统计、多租户隔离监控

超大宽表多维分析、复杂 JOIN 经营报表

存储压缩

时序专属压缩,冷数据压缩比可达 20:1

列式压缩,宽表场景压缩表现优秀

运维门槛

自带分片、冷热分层、TTL,开箱即用

需要手动规划分区、排序键、集群分片策略

生态适配

IoT、工业监控、设备时序场景生态完善

大数据分析、数仓建模生态更成熟

五、最终选型建议(支付场景专属)

选 TDengine 的情况

  • 核心诉求是商户隔离的实时监控、分钟级对账大盘,标签维度固定、时序窗口查询极多;
  • 多租户体量极大,需要天然的数据隔离、极简的冷热分层运维;
  • 以高频时序指标写入、降采样查询为主,极少做超复杂多表 JOIN 分析。

选 ClickHouse 的情况

  • 要做全链路交易宽表分析,字段会频繁扩展、需要做多维度交叉分析、复杂经营报表;
  • 团队熟悉 SQL 生态,希望复用 MySQL 开发习惯,同时对接现有大数据体系;
  • 单次分析的数据跨度极大(跨年全量审计),强依赖向量化计算提速。

最佳架构方案(中大型支付公司通用)

  • TDengine:承接网关打点、商户实时监控、秒级大盘指标;
  • ClickHouse:承接全量交易流水宽表存储、月度 / 年度复杂对账经营分析;
  • MySQL:承载核心订单主事务数据,三者分工解耦,兼顾事务、实时监控、深度分析三类需求。

结尾

时序类业务没有绝对的最优解,只有最贴合场景的选型:追求时序轻量化、多租户实时监控选 TDengine;追求通用宽表分析、复杂数仓建模选 ClickHouse,二者配合可以覆盖支付业务从交易落地到经营复盘的全链路需求。

Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐