本文为个人学习《Expert Oracle Database Architecture Techniques and Solutions for High Performance and Productivity(第四版本》一书过程中的笔记与理解分享,仅用于学习与交流,部分内容参考原书观点并结合>实际经验进行整理。若涉及版权问题,请联系删除或沟通处理。也请大家支持购买原版书籍。
Oracle 数字类型(下篇):浮点数、别名与性能陷阱
上一篇讲了最常用、最精确的 NUMBER 类型。这一篇我们来聊聊那些“不精确”但“速度快”的类型,以及一些你可能见过的“别名”。
一、浮点数类型:快,但不准
Oracle 支持两种标准的浮点数:
-
BINARY_FLOAT:单精度浮点数。 -
BINARY_DOUBLE:双精度浮点数。
它们最大的特点就是:用硬件直接计算,速度非常快! 但代价是:它们存储的是近似值,不是精确值。
这就像你用尺子测量,NUMBER 类型是游标卡尺,能精确到 0.01 毫米;而浮点类型就像是普通的直尺,只能精确到毫米。
一个可怕的例子:
如果你用浮点数做金融计算,可能会发现:
SELECT TO_CHAR(0.3F + 0.1F, '0.99999999999999') FROM dual;
-- 结果不是 0.4,而是:
-- 0.40000000600000这可不是 Bug! 这就是浮点数的工作原理。所以,记住一个铁律:
千万不能用
BINARY_FLOAT或BINARY_DOUBLE来存钱! 它们只适用于科学计算、数据挖掘等可以接受近似值的场景。
它们的语法很简单,没有参数:
CREATE TABLE science_data (
float_val BINARY_FLOAT,
double_val BINARY_DOUBLE
);二、数字类型的“别名”
你可能在其他数据库或者SQL语句里见过这些类型:INT, INTEGER, SMALLINT, DECIMAL, NUMERIC, FLOAT, REAL, DOUBLE PRECISION。
在 Oracle 里,它们全都是 NUMBER 类型的“马甲”或“别名”!
Oracle 为了兼容其他数据库的语法,允许你使用这些名字,但在底层,它们都会被悄悄换成 NUMBER 类型。所以,不管你写 INT 还是 DECIMAL(10,2),最终的效果和直接写 NUMBER 是一样的。
真正原生的数字类型只有三个:NUMBER, BINARY_FLOAT, BINARY_DOUBLE。
三、最重要的部分:性能权衡
这是最核心的抉择:要精确,还是要速度?
NUMBER类型:精确但慢
- 它是在 Oracle 软件里模拟实现的,CPU 需要做更多工作来计算。
- 适合: 几乎所有业务场景,尤其是会计、金融、电商等要求计算绝对准确的领域。
- 浮点类型:快但不精确
- 直接调用 CPU 的硬件指令计算,速度极快。
- 适合: 海量数据的科学计算、数学模型、统计分析,可以接受微小误差的场景。
性能差距有多大?
一个测试:对 7 万行数据做自然对数(LN)求和。
- 用
NUMBER类型计算: 耗时约 4.66 秒 - 用
BINARY_DOUBLE类型计算: 耗时约 0.06 秒
速度相差超过 70 倍! 但是,NUMBER 给出的结果是 734280.3209126472927309,而浮点数给出的结果是 734280.3209126447300000,后者存在微小的误差。
四、鱼与熊掌可以兼得吗?可以!
如果你遇到这种情况:“数据必须用 NUMBER 精确存储,但某些复杂计算又需要浮点数的速度”,怎么办?
Oracle 提供了一个两全其美的方案:CAST 函数。
你可以在计算时,临时把 NUMBER 类型的数据转换为浮点数,算完就完事,不影响存储精度。
-- 存储用精确的NUMBER
SELECT SUM(LN(CAST(num_type AS BINARY_DOUBLE))) FROM t;这样操作后,计算速度基本和直接使用 BINARY_DOUBLE 类型一样快!(上述查询耗时约 0.08 秒)。
总结
选择数字类型的决策流程非常简单:
- 默认无脑选
NUMBER:准没错,尤其涉及金额。 - 追求极致计算速度,且能接受误差? 选
BINARY_FLOAT或BINARY_DOUBLE。 - 又想精确存储,又想快速计算? 用
NUMBER存,用CAST(... AS BINARY_DOUBLE)算。 - 看见
INT,DECIMAL等关键字:知道它们是NUMBER的别名就好,效果一样。
希望这两篇文章能让你彻底明白如何在 Oracle 里处理数字!
------------------作者介绍-----------------------
姓名:黄廷忠
















