Перестраивается ли индекс автоматически?

В литературе часто можно встретить утверждение о том, что многочисленные индексы замедляют вставку, так как им приходится перестраиваться. В документации описание этого не нашел.

Проэкспериментировал, но перестройки индекса после вставки так и не обнаружил. Где же истина?

create table t 
(
    i int,
    str varchar2(100)
);

select * from t;

create index t_ind on t(i, str);

select * from all_indexes where index_name = 'T_IND'; 

insert into t
select level, dbms_random.string('X', 60) from dual connect by level < 1e3;

commit;

-- Данные по индексу (blevel, leaf_blocks) все еще пусты (0)

alter index t_ind rebuild;

-- Теперь значения изменились

Ответы (1 шт):

Автор решения: 0xdb

многочисленные индексы замедляют вставку, так как им приходится перестраиваться.

Это неверное утверждение (может машинный перевод). Индексы никогда не перестраиваются (rebuild) при выполнении DML, они изменяются в соответствии с изменениями записей в таблице.

Некоторые столбцы в представлениях:

(user|all|dba)_indexes (..., num_rows,blevel,leaf_blocks,...)

, отражают статистику собранную по индексу.

Сбор статистики не происходит сразу же после изменения индекса, а выполняется регулярно, как описано здесь.

После массовых изменений в таблице рекомендуется вручную собрать статистику по таблице. С параметром cascade=>true будет собрана также статистика по всем индексам таблицы.

create table t1 (i int, str varchar2 (100))
/
create index t1_ind on t1 (i, str);
/
prompt  &_date
2020-05-15 13:15:38

insert into t1
select level, dbms_random.string('X', 60) from dual connect by level <= 1e3;
commit;

select num_rows, blevel, leaf_blocks, last_analyzed 
from user_indexes where index_name = upper ('t1_ind'); 

  NUM_ROWS     BLEVEL LEAF_BLOCKS LAST_ANALYZED      
---------- ---------- ----------- -------------------
         0          0           0 2020-05-15 13:15:36

В столбеце LAST_ANALYZED время создания индекса, не массовой вставки. Сбор статистики:

exec dbms_stats.gather_table_stats (user, 't1', cascade=>true)

select num_rows, blevel, leaf_blocks, last_analyzed 
from user_indexes where index_name = upper ('t1_ind'); 

  NUM_ROWS     BLEVEL LEAF_BLOCKS LAST_ANALYZED      
---------- ---------- ----------- -------------------
      1000          1          10 2020-05-15 13:17:48
→ Ссылка