TDengine DECIMAL 数据类型使用手册

发布于:2025-07-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

在这里插入图片描述

TDengine DECIMAL 数据类型使用手册

1. 概述

DECIMAL 数据类型用来存储高精度数值数据,在其他数据库也被称为 NUMERICDECIMAL 数据类型的基本运算返回的是精确结果,适用于需要精确计算的场景,如金融数据、货币计算等。

相比于浮点数类型(FLOAT、DOUBLE),DECIMAL 类型:

  • 优势:保证精确计算,避免浮点数舍入误差
  • 劣势:计算性能相对较低

2. 基本概念

2.1 核心术语

DECIMAL 数据类型中有两个重要术语:

  • Precision(精度):指整个数值中有效数字个数,包括小数点左右两侧的所有数字。PRECISION 最大值为 MAX_PRECISION
  • Scale(标度):指位于小数点右侧的小数个数,必须为非负整数。SCALE 必须小于等于指定的 PRECISION 值,且 SCALE 最大值为 MAX_SCALE

2.2 定义示例

定义一个 DECIMAL(4,2) 数据类型:

  • 有效数字最多为 4 个
  • 小数点右侧 2 位
  • 表示的值范围为:[-99.99, 99.99]

2.3 约束限制

  • 不支持 DECIMAL UNSIGNED
  • 只在 Linux、Mac、Windows 平台支持
  • MAX_PRECISION 值为 38MAX_SCALE 值也为 38(采用 ClickHouse 中 Decimal128 相同行为)

3. 语法定义

3.1 基本语法

DECIMAL(precision, scale)   -- 完整格式
DECIMAL(precision)          -- scale 默认为 0

3.2 参数说明

  • precision:必须为正整数,取值范围 [1, MAX_PRECISION]
  • scale:必须为非负整数,取值范围 [0, min(MAX_SCALE, precision)]
  • 不指定 scale 时,默认为 0,即只表示整数
  • precision 等于 scale,则只能表示 (-1,1) 范围内的值

3.3 示例

-- 创建表使用 DECIMAL 类型
CREATE TABLE financial_data (
    ts TIMESTAMP,
    amount DECIMAL(10,2),     -- 10位精度,2位小数
    rate DECIMAL(5,4),        -- 5位精度,4位小数
    count DECIMAL(8)          -- 8位精度,0位小数(整数)
);

3.4 存储规则

  • 根据数据大小自动选择 Decimal64Decimal128 进行存储
  • Decimal64:8字节,最大精度18位
  • Decimal128:16字节,最大精度38位

注意:不支持 precisionscale 都不指定的方式定义 DECIMAL 类型。

4. 数据操作

4.1 插入数据

DECIMAL 类型数据可以通过多种方式插入:

4.1.1 数值格式插入
-- 插入数值,不会降低精度
INSERT INTO financial_data VALUES (NOW(), 123.45, 0.1250, 1000);
4.1.2 字符串格式插入
-- 插入字符串格式的数值
INSERT INTO financial_data VALUES (NOW(), '999.99', '0.9999', '99999999');
4.1.3 科学计数法插入
-- 支持科学计数法,形如 1E-37 即 1×10^(-37)
INSERT INTO financial_data VALUES (NOW(), 1.23E2, 1.5e-3, 1E6);

4.2 数据精度处理

4.2.1 精度截断

当插入数值的 scale 高于列定义的 scale 时,会进行四舍五入:

-- 列定义为 DECIMAL(3,1)
INSERT INTO test_table VALUES (0.11);  -- 实际存储为 0.1
4.2.2 溢出检查

当插入的数值超出精度范围时,会报 Decimal field overflow 错误:

-- 列定义为 DECIMAL(3,1),有效范围 [-99.9, 99.9]
INSERT INTO test_table VALUES (100.1);  -- 报错:Decimal field overflow

4.3 查询显示

查询结果的显示格式受 DECIMAL 的 PRECISIONSCALE 控制:

-- 对于 DECIMAL(5,2) 列
SELECT amount FROM financial_data;  -- 值 2.3 显示为 2.30

5. 表达式计算

5.1 常量处理

查询中的数值常量使用整数或 DOUBLE 类型解释,不会自动解释为 DECIMAL 类型。如需使用 DECIMAL 类型,可以手动进行类型转换:

-- 常量被解释为 DOUBLE
SELECT 3.14159 + amount FROM financial_data;

-- 手动转换为 DECIMAL
SELECT CAST(3.14159 AS DECIMAL(10,5)) + amount FROM financial_data;

5.2 运算规则

5.2.1 基本运算

DECIMAL 类型支持的基本运算符:+-*/%>>=<<==!=

5.2.2 运算结果类型
运算类型 运算符 输出类型 Scale 规则
decimal + decimal + DECIMAL max(S1, S2)
decimal - decimal - DECIMAL max(S1, S2)
decimal * decimal * DECIMAL MIN(MAX_SCALE, S1 + S2)
decimal / decimal / DECIMAL S1
decimal op float/double +,-,*,/ DOUBLE -
decimal op integer +,-,*,/ DECIMAL -

5.3 比较运算

DECIMAL 类型作为数值类型,在与其他数值类型比较时,遵循数值比较规则:

-- 以下比较结果为 true
SELECT 1.1000::DECIMAL(5,4) = 1.1::DECIMAL(3,1);    -- DECIMAL 之间
SELECT 123::DECIMAL(3,0) = 123;                      -- DECIMAL 与整数
SELECT 1.11::DECIMAL(3,2) = 1.11::FLOAT;            -- DECIMAL 与浮点数

5.4 溢出处理

  • 若计算结果值大于 MAX_PRECISION 时可表示的最大值,则报 overflow 错误
  • 若计算结果未溢出,但小数点左侧位数大于 MAX_PRECISION - SCALE,则自动截断,减小 SCALE

5.5 类型转换规则

操作符两侧不同类型字段计算时的转换规则:

源类型 目标类型 说明
NULL NULL 保持 NULL
BOOL/TINYINT/SMALLINT/INT/BIGINT DECIMAL 整数类型转换为 DECIMAL
UTINYINT/USMALLINT/UINT/UBIGINT DECIMAL 无符号整数转换为 DECIMAL
FLOAT/DOUBLE DOUBLE 浮点数运算结果为 DOUBLE
VARCHAR/TIMESTAMP DECIMAL 字符串和时间戳转换为 DECIMAL
NCHAR/BINARY DOUBLE 转换为 DOUBLE
JSON/VARBINARY/GEOMETRY 错误 不支持转换

6. 函数支持

6.1 函数返回类型

DECIMAL 类型支持的函数及其返回类型:

6.1.1 数学函数
函数 返回类型 说明
ABS(decimal) DECIMAL 绝对值
ROUND(decimal) DECIMAL 四舍五入
FLOOR(decimal) DECIMAL 向下取整
CEIL(decimal) BIGINT 向上取整
ACOS/ASIN/ATAN/COS/SIN/TAN DOUBLE 三角函数
LOG/POW/SQRT DOUBLE 对数、幂、平方根
6.1.2 聚合函数
函数 返回类型 说明
SUM(decimal) DECIMAL 求和
AVG(decimal) DECIMAL 平均值
MAX(decimal) DECIMAL 最大值
MIN(decimal) DECIMAL 最小值
COUNT(decimal) BIGINT 计数
6.1.3 窗口函数
函数 返回类型 说明
FIRST(decimal) DECIMAL 首个值
LAST(decimal) DECIMAL 最后值
APERCENTILE(decimal, p) DECIMAL 百分位数
PERCENTILE(decimal, p) DECIMAL 百分位数
SPREAD(decimal) DECIMAL 极差
6.1.4 时间序列函数
函数 返回类型 说明
CSUM(decimal) DECIMAL 累积和
DERIVATIVE(decimal) DECIMAL 导数
DIFF(decimal) DECIMAL 差分
MAVG(decimal, k) DECIMAL 移动平均
IRATE(decimal) DOUBLE 瞬时速率
TWA(decimal) DOUBLE 时间加权平均
6.1.5 统计函数
函数 返回类型 说明
STDDEV(decimal) DOUBLE 标准差
HISTOGRAM(decimal, bins) DOUBLE/BIGINT 直方图
HYPERLOGLOG(decimal) INTEGER 基数估计

6.2 类型转换函数

-- CAST 函数支持
SELECT CAST(123.456 AS DECIMAL(10,2));          -- 结果: 123.46
SELECT CAST('999.99' AS DECIMAL(8,2));          -- 结果: 999.99
SELECT CAST(column1 AS DECIMAL(15,4)) FROM t1;  -- 类型转换

7. 使用示例

7.1 创建表和插入数据

-- 创建包含 DECIMAL 类型的表
CREATE TABLE finance_records (
    ts TIMESTAMP,
    account_id INT,
    amount DECIMAL(15,2),      -- 金额:15位精度,2位小数
    rate DECIMAL(8,6),         -- 利率:8位精度,6位小数
    balance DECIMAL(20,2),     -- 余额:20位精度,2位小数
    quantity DECIMAL(10,0)     -- 数量:10位精度,0位小数(整数)
);

-- 插入数据
INSERT INTO finance_records VALUES 
    (NOW(), 1001, 1234.56, 0.025000, 10000.00, 100),
    (NOW(), 1002, 2345.67, 0.030000, 25000.00, 200),
    (NOW(), 1003, 3456.78, 0.035000, 50000.00, 300);

7.2 查询计算示例

-- 基本查询
SELECT account_id, amount, rate, balance FROM finance_records;

-- 计算利息
SELECT 
    account_id,
    amount,
    rate,
    amount * rate AS interest,
    balance + amount * rate AS new_balance
FROM finance_records;

-- 聚合统计
SELECT 
    SUM(amount) AS total_amount,
    AVG(rate) AS avg_rate,
    MAX(balance) AS max_balance,
    MIN(balance) AS min_balance
FROM finance_records;

-- 条件查询
SELECT * FROM finance_records 
WHERE amount > 2000.00 AND rate >= 0.030000;

7.3 精度控制示例

-- 创建不同精度的表
CREATE TABLE precision_test (
    ts TIMESTAMP,
    small_decimal DECIMAL(5,2),    -- 范围:-999.99 to 999.99
    medium_decimal DECIMAL(10,4),  -- 范围:-999999.9999 to 999999.9999
    large_decimal DECIMAL(18,6)    -- 范围:-999999999999.999999 to 999999999999.999999
);

-- 插入测试数据
INSERT INTO precision_test VALUES 
    (NOW(), 123.45, 1234.5678, 123456789.123456),
    (NOW(), 999.99, 999999.9999, 999999999999.999999);

-- 精度截断示例
INSERT INTO precision_test VALUES 
    (NOW(), 123.456, 1234.56789, 123456789.1234567);
-- 实际存储为:123.46, 1234.5679, 123456789.123457(四舍五入)

7.4 类型转换示例

-- 字符串转 DECIMAL
SELECT CAST('12345.67' AS DECIMAL(10,2)) AS decimal_value;

-- 整数转 DECIMAL
SELECT CAST(12345 AS DECIMAL(10,2)) AS decimal_value;

-- DECIMAL 转字符串
SELECT CAST(amount AS VARCHAR(20)) AS amount_str FROM finance_records;

-- 混合类型计算
SELECT 
    amount,
    CAST(amount AS FLOAT) AS amount_float,
    amount + 100 AS amount_plus_int,
    amount * 1.1 AS amount_times_float  -- 结果为 DOUBLE
FROM finance_records;

8. 客户端和API支持

8.1 C API

8.1.1 查询结果处理

使用 C API 的 taos_fetch_row 查询 DECIMAL 类型数据时,该列数据会被转换为字符串类型返回:

// 查询 DECIMAL 类型数据
TAOS_RES *res = taos_query(taos, "SELECT amount FROM finance_records");
TAOS_ROW row;
while ((row = taos_fetch_row(res)) != NULL) {
    // DECIMAL 列作为字符串读取
    char *amount_str = (char *)row[0];
    printf("Amount: %s\n", amount_str);
}
8.1.2 Raw Block 解析

调用 taos_fetch_raw_block 接口时,Raw Block 内结构保持不变:

  • DECIMAL64:8字节定长字段
  • DECIMAL128:16字节定长字段
  • Schema 信息存储格式:
字段 长度 说明
bytes 1字节 所需大小(8/16)
empty 1字节 保留字段
precision 1字节 精度值
scale 1字节 标度值
8.1.3 解析 DECIMAL 数据

Decimal64 解析:

// 8字节数据转换为 int64_t
int64_t decimal64_value = *(int64_t*)data;
// 根据 scale 计算实际值
double actual_value = (double)decimal64_value / pow(10, scale);

Decimal128 解析:

// 16字节数据转换为 int128(小端序)
// 需要自定义 int128 处理或使用库函数
// 根据 scale 计算实际值

8.2 连接器支持

各语言连接器对 DECIMAL 类型的支持:

连接器 支持状态 返回类型 说明
Java 支持 BigDecimal 完整精度支持
Python 支持 Decimal 使用 decimal 模块
Go 支持 string 字符串形式返回
Node.js 支持 string 字符串形式返回
C# 支持 decimal .NET Decimal 类型
Rust 支持 string 字符串形式返回

8.3 工具支持

8.3.1 taos Shell
# 查看表结构
taos> DESC finance_records;
# 输出示例:
# amount    | DECIMAL(15,2) | ...

# 查询数据
taos> SELECT amount FROM finance_records;
# 输出格式按照 DECIMAL 定义的精度显示
8.3.2 taosBenchmark

taosBenchmark 支持 DECIMAL 类型的性能测试:

# 创建包含 DECIMAL 类型的测试表
taosbenchmark -P 6030 -d test_db -t 10 -n 100000 \
  --columns "amount DECIMAL(15,2),rate DECIMAL(8,6)"

9. 性能特性

9.1 性能对比

DECIMAL 类型相比于其他数值类型的性能特性:

操作类型 DECIMAL INT/BIGINT FLOAT/DOUBLE 性能比较
插入 正常 最快 DECIMAL < FLOAT < INT
查询 正常 最快 DECIMAL < FLOAT < INT
运算 最快 DECIMAL 比其他类型慢 30-50%
聚合 最快 DECIMAL 比其他类型慢 30-50%

9.2 存储优化

  • 压缩算法:DECIMAL 类型提供专门的压缩算法
  • 存储格式:根据精度自动选择 Decimal64 或 Decimal128
  • 内存使用:相比字符串存储数值更节省空间

9.3 计算优化

  • 批量计算:支持向量化计算,提高批量处理性能
  • 缓存优化:频繁使用的精度信息进行缓存
  • 并行计算:支持多线程并行处理

10. 使用场景

10.1 适用场景

DECIMAL 类型特别适合以下场景:

  1. 金融系统

    • 货币计算
    • 利率计算
    • 财务报表
    • 交易记录
  2. 科学计算

    • 精确测量数据
    • 统计分析
    • 实验数据记录
  3. 商业应用

    • 价格计算
    • 税务计算
    • 库存管理
    • 成本分析

10.2 典型应用

-- 金融应用示例
CREATE TABLE account_transactions (
    ts TIMESTAMP,
    account_id BIGINT,
    transaction_type VARCHAR(20),
    amount DECIMAL(18,2),           -- 交易金额
    balance DECIMAL(20,2),          -- 账户余额
    exchange_rate DECIMAL(10,6),    -- 汇率
    fee DECIMAL(8,4)                -- 手续费
);

-- 科学数据示例
CREATE TABLE sensor_data (
    ts TIMESTAMP,
    sensor_id INT,
    temperature DECIMAL(6,3),       -- 温度(精确到千分位)
    pressure DECIMAL(8,2),          -- 压力
    humidity DECIMAL(5,2),          -- 湿度
    coordinate_x DECIMAL(15,8),     -- 坐标(高精度)
    coordinate_y DECIMAL(15,8)
);

10.3 不适用场景

以下场景不建议使用 DECIMAL 类型:

  1. 高频交易:对性能要求极高的场景
  2. 简单计数:整数计数场景直接使用 INT/BIGINT
  3. 近似计算:不需要精确计算的场景可使用 FLOAT/DOUBLE
  4. 日志数据:大量日志数据建议使用性能更好的类型

11. 约束与限制

11.1 系统约束

  • 平台支持:仅支持 Linux、macOS、Windows 平台
  • 精度限制
    • MAX_PRECISION = 38(最大精度)
    • MAX_SCALE = 38(最大标度)
    • SCALE ≤ PRECISION(标度不能超过精度)

11.2 功能限制

11.2.1 当前不支持的功能
  • 标签列:DECIMAL 类型不能用作标签列
  • Schema 修改:不支持修改 DECIMAL 类型的 precisionscale
  • Schemaless 写入:暂不支持无模式写入 DECIMAL 数据
  • Stmt 参数绑定:暂不支持预处理语句参数绑定
11.2.2 部分支持的功能
  • UDF 支持:用户定义函数对 DECIMAL 类型支持有限
  • 数学函数:部分高级数学函数(如对数、三角函数等)返回 DOUBLE 类型

11.3 兼容性约束

  • 版本兼容:创建 DECIMAL 类型后不能回退到不支持 DECIMAL 的版本
  • 组件兼容
    • 流计算:支持
    • 数据订阅:支持,需要类型转换
    • SMA 索引:需要重新计算
    • 连续查询:支持

11.4 性能约束

  • 计算性能:比 INT/FLOAT 类型慢 30-50%
  • 存储开销:比对应的整数类型占用更多空间
  • 内存使用:计算过程中需要更多内存

11.5 数据范围约束

根据精度和标度的不同,DECIMAL 类型的数值范围如下:

精度 标度 数值范围示例
DECIMAL(3,0) 0 -999 to 999
DECIMAL(3,1) 1 -99.9 to 99.9
DECIMAL(5,2) 2 -999.99 to 999.99
DECIMAL(10,4) 4 -999999.9999 to 999999.9999
DECIMAL(18,6) 6 -999999999999.999999 to 999999999999.999999

12. 故障排除

12.1 常见错误

12.1.1 精度溢出错误
-- 错误示例
CREATE TABLE test (id INT, amount DECIMAL(5,2));
INSERT INTO test VALUES (1, 12345.67);  -- 错误:Decimal field overflow

解决方案:增加精度或减少数值大小

12.1.2 类型转换错误
-- 错误示例
SELECT amount + 'abc' FROM test;  -- 错误:Invalid type conversion

解决方案:确保参与运算的数据类型兼容

12.1.3 精度定义错误
-- 错误示例
CREATE TABLE test (amount DECIMAL(5,6));  -- 错误:Scale 不能大于 Precision

解决方案:确保 scale ≤ precision

12.2 性能问题

12.2.1 计算性能慢

问题:DECIMAL 类型计算比其他数值类型慢

解决方案

  • 评估是否真的需要 DECIMAL 精度
  • 考虑使用 BIGINT 存储整数部分,必要时转换
  • 批量计算时考虑使用更高效的数据类型
12.2.2 查询性能优化

建议

  • 对 DECIMAL 列创建适当的索引
  • 避免在 WHERE 子句中对 DECIMAL 列进行复杂计算
  • 使用批量插入提高写入性能

12.3 数据一致性

12.3.1 精度损失问题

问题:插入时精度超出定义范围

解决方案

  • 检查输入数据的精度
  • 适当调整 DECIMAL 类型的精度定义
  • 在应用层进行数据验证

13. 最佳实践

13.1 设计建议

  1. 合理选择精度:根据业务需求选择合适的精度,避免过度设计
  2. 统一精度标准:同一业务域的 DECIMAL 类型保持一致的精度
  3. 考虑性能影响:在性能敏感的场景中谨慎使用 DECIMAL 类型
  4. 数据验证:在应用层对 DECIMAL 数据进行有效性验证

13.2 使用建议

  1. 金融数据:推荐使用 DECIMAL(18,2) 或 DECIMAL(20,2)
  2. 比率数据:推荐使用 DECIMAL(8,6) 或 DECIMAL(10,6)
  3. 测量数据:根据测量精度选择合适的标度
  4. 计算结果:考虑中间计算结果的精度需求

13.3 运维建议

  1. 监控性能:定期监控 DECIMAL 类型相关查询的性能
  2. 存储规划:考虑 DECIMAL 类型对存储空间的影响
  3. 备份策略:确保备份恢复过程中 DECIMAL 数据的完整性
  4. 版本升级:升级前确认 DECIMAL 类型的兼容性

14. 参考信息

14.1 相关文档

  • TDengine 数据类型文档
  • TDengine SQL 参考手册
  • TDengine 连接器文档
  • TDengine 性能优化指南

14.2 版本支持

  • v3.3.6.0:引入 DECIMAL 类型支持

14.3 技术支持

如遇到 DECIMAL 类型相关问题,请:

  1. 查阅官方文档
  2. TDengine 社区论坛提问
  3. 联系技术支持团队
  4. 提交 GitHub Issues