Индекс по номеру столбца в Oracle 10g - PullRequest
2 голосов
/ 25 января 2012

в настоящее время у нас есть столбец, в котором только целые значения объявлены как NUMBER.В то же время это наш (единственный) индекс.Интересно, будет ли разница в производительности, если вы объявите индекс как INTEGER?Или Oracle достаточно умен, чтобы видеть, что это целое число?Большое спасибо.

Ответы [ 2 ]

4 голосов
/ 25 января 2012

Нет, не будет.

Используя тестовые таблицы Флорина, вы можете настроить небольшую тестовую систему, которая будет выполнять каждый запрос сотни раз и в среднем затраченное время.В моем случае я выполнял оба запроса по 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 строк, а не 1 миллион), изменений нет

Создать таблицу

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
0 голосов
/ 25 января 2012

ОБНОВЛЕНИЕ: у моего теста была небольшая проблема. (Я пытался в первой таблице вставить 10M строк, но при подключении возникло исключение недостаточной памяти. Однако, вероятно, было вставлено 2-3M строк, а затем выполено. Таким образом, моя первая таблица имела такое же количество строк, но больше блоков .)

Итак, приведенные ниже утверждения не проверены.

Ответ - да.

(но сколько вы получите от этого, вам следует протестировать свои критические операции.)

INTEGER является подтипом NUMBER. Но, что удивительно, подтипы 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(*) несколько раз, чтобы посмотреть, какова лучшая скорость. В общем, с INTEGER это faster. Лучшая скорость INTEGER лучше , чем лучшая скорость NUMBER;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...