在支付风控、对账大盘、交易溯源这类强时序特征的业务里,很多团队会纠结选专用时序库 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_id、pay_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,二者配合可以覆盖支付业务从交易落地到经营复盘的全链路需求。