zoukankan      html  css  js  c++  java
  • 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-------

  • 相关阅读:
    Leetcode 1489找到最小生成树李关键边和伪关键边
    Leetcode 113 路径总和 II
    hdu 1223 还是畅通工程
    hdu 1087 Super Jumping! Jumping! Jumping!
    hdu 1008 Elevator
    hdu 1037 Keep on Truckin'
    湖工oj 1241 畅通工程
    湖工oj 1162 大武汉局域网
    hdu 2057 A + B Again
    poj 2236 Wireless Network
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4313706.html
Copyright © 2011-2022 走看看