author:skate

time:2011-02-14


oracle的number的浅析

从例如以下几个方面来认识number

1.表示的数值范围
   2.占用的存储空间
   3.number的性能

我们日常主要定义数值存储列是大都是用number,只是oracle也兼容一些以他类型,例如以下:

NUMERIC(p,s):全然映射至NUMBER(p,s)。假设p未指定,则默觉得38.
DECIMAL(p,s)或DEC(p,s):全然映射至NUMBER(p,s)。假设p为指定,则默觉得38.
INTEGER或INT:全然映射至NUMBER(38)类型。
SMALLINT:全然映射至NUMBER(38)类型。
FLOAT(b):映射至NUMBER类型。
DOUBLE PRECISION:映射至NUMBER类型。
REAL:映射至NUMBER类型。

以上这些类型仅仅是oracle在语法上支持的,在底层实际上还是number

1.表示的数值范围

NUMBER:Oracle NUMBER类型能以极大的精度存储数值,详细来讲,精度可达38位。其底层数据格式相似一种
       “封包小数“表示。Oracle NUMBER类型是一种变长格式,长度为0~22字节。它能够存储小到10e-130、
        大到(但不包含)10e126的不论什么数值。这是眼下最为经常使用的数值类型。也是Oracle9i Release 2及以
        前的版本号仅仅支持的唯一一种适合存储数值数据的固有数据类型,其它一起兼容类型仅仅是一种和number
        之间的映射,在底层实际上都是number

BINARY_FLOAT:这是一种IEEE固有的单精度浮点数。它在磁盘上会占用5字节的存储空间:当中4个固定字节用
              于存储浮点数,另外另一个长度字节。BINARY_FLOAT能存储有6为精度、范围在~±1038.53
              的数值

BINARY_DOUBLE:这是一种IEEE固有的双精度浮点数。它在磁盘上会占用9字节的存储空间:当中8个固定字节用
               于存储浮点数,另一个长度字节。BINARY_DOUBLE能存储有12.位精度、范围在~±10308.25的
               数值。

取值范举例:

创建測试表t2
SQL>  create table t2
  2   ( num_type number,
  3     float_type binary_float,
  4     double_type binary_double
  5   );

Table created

插入測试数据1
SQL>
SQL> insert into t2
  2    (num_type, float_type, double_type)
  3  values
  4    (1234567890.0987654321, 1234567890.0987654321, 1234567890.0987654321);

1 row inserted

查看測试数据1
SQL>
SQL>  select to_char(num_type),
  2          to_char(float_type, '999999999999.999999999'),
  3          to_char(double_type, '99999999999.9999999999')
  4     from t2
  5  ;

TO_CHAR(NUM_TYPE)               TO_CHAR(FLOAT_TYPE,'9999999999            TO_CHAR(DOUBLE_TYPE,'999999999
--------------------------- -----------------------------------------------------------------------------------
1234567890.0987654321            1234567940.000000000                        1234567890.0987654000

插入測试数据2
SQL>
SQL> insert into t2
  2    (num_type, float_type, double_type)
  3  values
  4    (12345678900987654321, 12345678900987654321, 12345678900987654321);

1 row inserted

查看測试数据2
SQL>
SQL>  select to_char(num_type),
  2          to_char(float_type, '999999999999999999999'),
  3          to_char(double_type, '999999999999999999999')
  4     from t2
  5  ;

TO_CHAR(NUM_TYPE)                        TO_CHAR(FLOAT_TYPE,'9999999999                                                   TO_CHAR(DOUBLE_TYPE,'999999999
---------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
1234567890.0987654321                                1234567940                                                                       1234567890
12345678900987654321                       12345679400000000000                                                             12345678900987654000

SQL>

从測试结果能够看到,number能够正确显示数据,精度非常高;binary_float仅仅正确的显示了前7位;binary_double显示的数据范围和精度要比binary_float高非常多。

2.占用的存储空间

number类型占用0-22个字节,它实际上是磁盘上的一个变长数据类型,是oracle依据一定算法,採用尽可能少存储空间表示一个数

SQL> create table t ( x number, y number );

Table created

SQL>
SQL>  insert into t ( x )
  2   select to_number(rpad('9',rownum*2,'9'),'999999999999999999999999999999999999999999999999999999999')
  3   from all_objects
  4   where rownum <= 25;

25 rows inserted

SQL> update t set y = x+1;

25 rows updated

SQL> column 数字1 format 9999999999999999999999999999999999999999999999999999999999999999999999999

SQL> column 数字2 format 9999999999999999999999999999999999999999999999999999999999999999999999999

SQL>  select to_char(x) 数字1, to_char(y) 数字2, vsize(x) 数字1占字节数, vsize(y) 数字2占字节数 from t order by x;

数字1                                             数字2                                       数字1占字节数 数字2占字节数
----------------------------------------------- ------------------------------------------------------------------------- ------------- -------------
99                                              100                                             2             2
9999                                            10000                                           3             2
999999                                          1000000                                         4             2
99999999                                        100000000                                       5             2
9999999999                                      10000000000                                     6             2
999999999999                                    1000000000000                                   7             2
99999999999999                                  100000000000000                                 8             2
9999999999999999                                10000000000000000                               9             2
999999999999999999                              1000000000000000000                            10             2
99999999999999999999                            100000000000000000000                          11             2
9999999999999999999999                          10000000000000000000000                        12             2
999999999999999999999999                        1000000000000000000000000                      13             2
99999999999999999999999999                      100000000000000000000000000                    14             2
9999999999999999999999999999                    10000000000000000000000000000                  15             2
999999999999999999999999999999                  1000000000000000000000000000000                16             2
99999999999999999999999999999999                100000000000000000000000000000000              17             2
9999999999999999999999999999999999              10000000000000000000000000000000000            18             2
999999999999999999999999999999999999            1000000000000000000000000000000000000          19             2
99999999999999999999999999999999999999          100000000000000000000000000000000000000        20             2
9999999999999999999999999999999999999999        1.0000000000000000000000000000000000E+40       21             2

数字1                                                                     数字2               数字1占字节数 数字2占字节数
--------------------------------------------------------------------------------------------------- ------------- -------------
1.0000000000000000000000000000000000E+42         1.0000000000000000000000000000000000E+42      2             2
1.0000000000000000000000000000000000E+44         1.0000000000000000000000000000000000E+44      2             2
1.0000000000000000000000000000000000E+46         1.0000000000000000000000000000000000E+46      2             2
1.0000000000000000000000000000000000E+48         1.0000000000000000000000000000000000E+48      2             2
1.0000000000000000000000000000000000E+50         1.0000000000000000000000000000000000E+50      2             2

25 rows selected

SQL>

从样例能够看出,在oracle存储有效数据(非0数据)时,每添加两位数,数据的存储空间就添加一个字节,直到数据溢出。
Oracle存储一个数时,会存储尽可能少的内容来表示这个数。为此会存储有效数字和用于指定小数点位置的一个指数,以及
有关数值符号的信息(正或负)。因此,数中包括的有效数字越多,占用的存储空间就越大。

BINARY_FLOAT与BINARY_DOUBLE

浮点数用于近似数值;它们没有Oracle内置的 NUMBER类型那么精确。浮点数经常使用在科学计算中,因为同意在硬件(CPU、芯片)
上运行运算,而不是在Oracle子例程中运算,所以在多种不同类型的应用中都非常实用。因此,假设在一个科学计算应用中运行
实数处理,算术运算的速度会快得多。

BINARY_FLOAT在磁盘上会占用5字节的存储空间:当中4个固定字节用于存储浮点数,另外另一个长度字节
BINARY_DOUBLE在磁盘上会占用9字节的存储空间:当中8个固定字节用于存储浮点数,另外另一个长度字节

3.number的性能
Oracle NUMBER类型对大多数应用来讲都是最佳的选择,尤其是经融行业,只是有利必有弊,number会带来性能的影响。
由于Oracle NUMBER类型是一种软件数据类型,是在Oracle软件本身中实现。我们不能使用固有硬件操作将两个NUMBER
类型相加,这要在软件中模拟,所以性能有非常大的影响,为此,oracle又提供的两个浮点类型的BINARY_FLOAT与BINARY_DOUBLE。

以下举例说明性能对照

创建測试表
SQL>  create table t2
  2   ( num_type number,
  3     float_type binary_float,
  4     double_type binary_double
  5   );

Table created

SQL>
SQL>  insert /*+ APPEND */ into t2
  2   select rownum, rownum, rownum
  3   from all_objects
  4  ;

57302 rows inserted

SQL> alter session set events '10046 trace name context forever ,level 1';

Session altered

SQL>  select sum(ln(num_type)) from t2;

SUM(LN(NUM_TYPE))
-----------------
 570510.312356972

SQL>  select sum(ln(float_type)) from t2;

SUM(LN(FLOAT_TYPE))
-------------------
    570510.31235697

SQL>  select sum(ln(double_type)) from t2;

SUM(LN(DOUBLE_TYPE))
--------------------
     570510.31235697

SQL>  select sum(ln(cast(num_type as binary_double ) )) from t2;

SUM(LN(CAST(NUM_TYPEASBINARY_D
------------------------------
               570510.31235697

SQL> alter session set events '10046 trace name context off ';

Session altered

SQL>

查看跟踪文件内容例如以下:

........

********************************************************************************

select sum(ln(num_type))
from
 t2

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          3          1           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      2.31       2.25         38        193          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      2.31       2.25         38        196          1           1

********************************************************************************

select sum(ln(float_type))
from
 t2

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          1          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.04       0.04          0        193          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.04       0.04          0        194          0           1

********************************************************************************

select sum(ln(double_type))
from
 t2

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          1          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.03       0.04          0        193          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.04       0.04          0        194          0           1

********************************************************************************

select sum(ln(cast(num_type as binary_double ) ))
from
 t2

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          1          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        1      0.10       0.09          0        193          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        3      0.10       0.10          0        194          0           1

从測试结果来看,number的性能确实非常慢,比浮点类型BINARY_FLOAT与BINARY_DOUBLE慢57倍多,只是能够cast函数来转换下,
在对number运行复杂数学运算之前先将其转换为一种浮点数类型,这样就会提高计算速度,但还是比直接用浮点类型慢非常多,
但也是一个折中的方法。

--------end-------

oracle的number的浅析的更多相关文章

  1. 【转】oracle数据库NUMBER数据类型

    原文:http://www.jb51.net/article/37633.htm NUMBER ( precision, scale)a)  precision表示数字中的有效位;如果没有指定prec ...

  2. oracle的resetlogs机制浅析

    oracle的resetlogs机制浅析 alter database open resetlogs 这个命令我想大家都很熟悉了,那有没有想过这个resetlogs选项为什么要用?什么时候用?它的原理 ...

  3. Oracle类型number与PG类型numeric对比和转换策略

    Oracle 11g number 任意精度数字类型 http://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT3 ...

  4. 对于Oracle中Number类型的字段映射成Java中的具体类型的问题

    我在Oracle中给一个用户Id字段设置为Number类型,使用JDBC在完成ORM的时候,以为其可以自动转换为Integer,因为我的POJO类id使用的就是Integer.但事实是,我在测试的时候 ...

  5. Oracle数据库 number 长度与 Short Integer Long BigDecimal 对应关系

    转自:https://blog.csdn.net/edward9145/article/details/21398657 Oracle数据库 number 长度与 Short Integer Long ...

  6. Oracle的number数据类型

    https://www.cnblogs.com/oumyye/p/4448656.html NUMBER ( precision, scale) precision表示数字中的有效位;如果没有指定pr ...

  7. ORACLE 中NUMBER类型默认的精度和Scale问题

    在ORACLE数据库中,NUMBER(P,S)是最常见的数字类型,可以存放数据范围为10^-130~10^126(不包含此值),需要1~22字节(BYTE)不等的存储空间.P 是Precison的英文 ...

  8. Oracle中number(5,-2)数据类型

    举个例子,1234.345 如果为number(5,-2),那么结果为 1200, 如果为number(5,2),那么结果为 1234.35 如果为number(5),那么结果为 1234 说明: N ...

  9. Spark SQL读取Oracle的number类型的数据时精度丢失问题

    Spark SQL读取数据Oracle的数据时,发现number类型的字段在读取的时候精度丢失了,使用的spark版本是Spark2.1.0的版本,竟然最后经过排查和网上查资料发现是一个bug.在Sp ...

随机推荐

  1. TOMCAT8009端口与AJP13协议

    Tomcat最主要的功能是提供Servlet/JSP容器,尽管它也可以作为独立的Java Web服务器,它在对静态资源(如HTML文件或图像文件)的处理速度,以及提供的Web服务器管理功能方面都不如其 ...

  2. jmeter与apache测试网站并发

    本文主要介绍性能测试中的常用工具jmeter的使用方式,以方便开发人员在自测过程中就能自己动手对系统进行自动压测和模拟用户操作访问请求.最后还用linux下的压测工具ab做了简单对比. 1.      ...

  3. [Angular] New async 'as' syntax and ngIf.. else

    From Anuglar v4 above, we are able to using 'as' with async pipe. This allow as using 'new variable' ...

  4. NSString常见用法

    1.创建常量字符串 NSString *str = @"Hello World!"; 2.创建空字符串,给予赋值 NSString *str = [[NSString alloc] ...

  5. width:100%和width:inherit

    前几天遇到过这么一个问题.我想让子盒子的宽度等于父盒子的宽度.父盒子宽度为一个具体值比如说200px.我将子盒子宽度设为了100%.按道理说应该是可以等于父盒子的宽度的,但结果并没有,而是通栏了.然后 ...

  6. java实现微信支付宝等多个支付平台合一的二维码支付(maven+spring springmvc mybatis框架)

    首先申明,本人实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,本人采用的框架是spring springmvc mybatis 框架,maven管理.其实如果支付,不需要my ...

  7. 分层抽样(Stratified sampling)

    1. 基本概念 统计学理论中,分层抽样针对的是对一个总体(population)进行抽样的方法.尤其适用于当总体内部,子总体(subpopulations)间差异较大时.每一个 subpopulati ...

  8. 是男人就下100层【第四层】——Crazy贪吃蛇(3)

    上一篇<是男人就下100层[第四层]--Crazy贪吃蛇(2)>实现了贪吃蛇绕着屏幕四周移动,这一篇我们来完成贪吃蛇的所有功能. 一.随机产生苹果 private void addAppl ...

  9. thinkphp 3.2,引入第三方类库的粗略记录

    首先用第三方类库我是放到vendor里面的 根目录\ThinkPHP\Library\Vendor\Wxphp 例如创建了一个Wxphp文件夹,里面有个php文件叫做     zll.php    文 ...

  10. php 文件夹是否存在,不存在就创建

    $lujing = "./nihao/wohao"; if(!is_dir($liujing)){ mkdir(iconv("UTF-8", "GBK ...