Oracle 10g上NUMBER列的索引

时间:2012-01-25 14:31:15

标签: database performance oracle

目前我们有一个只有整数值声明为NUMBER的列。同时它是我们的(唯一)索引。我想知道如果你将索引声明为INTEGER会对性能产生影响吗?或者Oracle是否足够聪明才能看到它是一个整数?非常感谢你。

2 个答案:

答案 0 :(得分:4)

不,它不会。

使用Florin的测试表,您可以设置一个小测试工具,每个查询运行数百次并平均经过的时间。就我而言,我分别运行了500次查询。

有时候,NUMBER版本的运行速度会稍微快一点(1.232百分之一秒对1.284百分之一秒)。

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_start_time number;
  3    l_end_time   number;
  4    l_cnt        number;
  5    l_iterations number := 500;
  6  begin
  7    l_start_time := dbms_utility.get_time();
  8    for i in 1 .. l_iterations
  9    loop
 10      select count(*)
 11        into l_cnt
 12        from fg_test;
 13    end loop;
 14    l_end_time := dbms_utility.get_time();
 15    dbms_output.put_line( 'Average elapsed (number) = ' ||
 16                             (l_end_time - l_start_time)/l_iterations ||
 17                             ' hundredths of a second.' );
 18    l_start_time := dbms_utility.get_time();
 19    for i in 1 .. l_iterations
 20    loop
 21      select count(*)
 22        into l_cnt
 23        from fg_test1;
 24    end loop;
 25    l_end_time := dbms_utility.get_time();
 26    dbms_output.put_line( 'Average elapsed (integer) = ' ||
 27                             (l_end_time - l_start_time)/l_iterations ||
 28                             ' hundredths of a second.' );
 29* end;
 30  /
Average elapsed (number) = 1.232 hundredths of a second.
Average elapsed (integer) = 1.284 hundredths of a second.

PL/SQL procedure successfully completed.

Elapsed: 00:00:12.60

但是,如果你立即再次运行相同的代码块,那么你很可能会看到整数版运行速度稍快的反向。

SQL> /
Average elapsed (number) = 1.256 hundredths of a second.
Average elapsed (integer) = 1.22 hundredths of a second.

PL/SQL procedure successfully completed.

Elapsed: 00:00:12.38

实际上,在您尝试测量毫秒或几分之一毫秒的差异时,您就可以进入系统噪声发挥作用的领域。尽管我正在运行的测试之外我的机器处于“空闲”状态,但有数千个原因可能导致系统为处理某些中断或运行某些后台线程而增加额外的毫秒或两秒时间。对于操作系统。

当您认为INTEGER只是NUMBER(38)

的同义词时,此结果很有意义
SQL> desc fg_test1;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                                  NUMBER(38)

SQL> desc fg_test;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                                  NUMBER

更新

即使使用NUMBER(6)(请注意,INSERT必须更改为仅加载999,999行而不是100万行),所以没有变化

创建表格

SQL> create table fg_test2(a number(6));

Table created.

Elapsed: 00:00:00.01

SQL> ed
Wrote file afiedt.buf

  1  insert into fg_test2
  2* select level from dual connect by level <= 1000000-1
SQL> /

999999 rows created.

Elapsed: 00:00:07.61

SQL> create index fg_ix2 on fg_test2(a);

Index created.

Elapsed: 00:00:00.01

运行脚本。请注意,四次运行中的任何一次都没有显着差异,并且(偶然)四种情况都不是NUMBER(6)表最有效。

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    l_start_time number;
  3    l_end_time   number;
  4    l_cnt        number;
  5    l_iterations number := 500;
  6  begin
  7    l_start_time := dbms_utility.get_time();
  8    for i in 1 .. l_iterations
  9    loop
 10      select count(*)
 11        into l_cnt
 12        from fg_test;
 13    end loop;
 14    l_end_time := dbms_utility.get_time();
 15    dbms_output.put_line( 'Average elapsed (number) = ' ||
 16                             (l_end_time - l_start_time)/l_iterations ||
 17                             ' hundredths of a second.' );
 18    l_start_time := dbms_utility.get_time();
 19    for i in 1 .. l_iterations
 20    loop
 21      select count(*)
 22        into l_cnt
 23        from fg_test1;
 24    end loop;
 25    l_end_time := dbms_utility.get_time();
 26    dbms_output.put_line( 'Average elapsed (integer) = ' ||
 27                             (l_end_time - l_start_time)/l_iterations ||
 28                             ' hundredths of a second.' );
 29    l_start_time := dbms_utility.get_time();
 30    for i in 1 .. l_iterations
 31    loop
 32      select count(*)
 33        into l_cnt
 34        from fg_test2;
 35    end loop;
 36    l_end_time := dbms_utility.get_time();
 37    dbms_output.put_line( 'Average elapsed (number(6)) = ' ||
 38                             (l_end_time - l_start_time)/l_iterations ||
 39                             ' hundredths of a second.' );
 40* end;
SQL> /
Average elapsed (number) = 1.236 hundredths of a second.
Average elapsed (integer) = 1.234 hundredths of a second.
Average elapsed (number(6)) = 1.306 hundredths of a second.

PL/SQL procedure successfully completed.

Elapsed: 00:00:18.89
SQL> /
Average elapsed (number) = 1.208 hundredths of a second.
Average elapsed (integer) = 1.228 hundredths of a second.
Average elapsed (number(6)) = 1.312 hundredths of a second.

PL/SQL procedure successfully completed.

Elapsed: 00:00:18.74
SQL> /
Average elapsed (number) = 1.208 hundredths of a second.
Average elapsed (integer) = 1.232 hundredths of a second.
Average elapsed (number(6)) = 1.288 hundredths of a second.

PL/SQL procedure successfully completed.

Elapsed: 00:00:18.66
SQL> /
Average elapsed (number) = 1.21 hundredths of a second.
Average elapsed (integer) = 1.22 hundredths of a second.
Average elapsed (number(6)) = 1.292 hundredths of a second.

PL/SQL procedure successfully completed.

Elapsed: 00:00:18.62

答案 1 :(得分:0)

更新:我的测试有一个小问题。 (我尝试第一个表插入10M行,但是连接已经引发了一个不足的内存异常。但是很可能插入了2-3M行然后进行了rolbaked。所以,我的第一个表有相同的行数,但是更多的块。)

因此,下面的断言未经过验证。

<击> 答案是肯定的。

(但是你从中获得了多少,你应该对你的关键操作进行测试。)

INTEGERNUMBER的子类型。但是,令人惊讶的是,NUMBER的子信息总是更快(需要链接在这里)。

我的测试用例:

create table fg_test(a number);

insert into fg_test 
select level from dual connect by level <= 1000000;
--1000000 rows inserted

create index fg_ix on fg_test(a);

select count(*) from fg_test;
-- >141 msecs

create table fg_test1(a INTEGER);

insert into fg_test1 
select level from dual connect by level <= 1000000;
--1000000 rows inserted

create index fg_ix1 on fg_test1(a);

select count(*) from fg_test1;
-- > 116 msecs

说明:select count(*)将对索引进行快速全面扫描。我跑了select count(*)多次,看看最好的速度是多少。通常,INTEGERfasterINTEGER的最佳速度更好,而不是NUMBER的最佳速度;