• oracle的number的浅析


    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-------

  • 相关阅读:
    实现移动端1像素线--stylus
    用户信息认证session和token
    深入了解new的过程,和call,apply,bind的区别
    微信公众号开发过程--踏坑指南
    Better-scroll巨坑!!!
    JS ES6中Arguments和Parameters的区别
    知识点1
    面试--随笔1
    pytts3语音合成遇到的中文问题
    需求,需要谁参与进来?
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4313706.html
Copyright © 2020-2023  润新知