A diferença é que coletar estatísticas atualiza os metadados sobre o índice atual, enquanto descartar e recriar o índice é descartar e recriar o índice.
Talvez seja fácil entender a diferença com um exemplo trabalhado. Então vamos criar uma tabela e um índice:
SQL> create table t23
2 as select object_id as id, object_name as name from user_objects
3 /
Table created.
SQL> create index i23 on t23(id)
2 /
Index created.
SQL> select o.object_id, i.last_analyzed, i.distinct_keys
2 from user_objects o
3 join user_indexes i
4 on (i.index_name = o.object_name)
5 where o.object_type = 'INDEX'
6 and i.index_name = 'I23'
7 /
OBJECT_ID CREATED LAST_ANALYZED DISTINCT_KEYS
---------- -------------------- -------------------- -------------
116353 23-NOV-2013 00:15:39 23-NOV-2013 00:15:39 167
1 row selected.
SQL>
Desde 11g o Oracle reúne automaticamente estatísticas quando criamos um índice. Portanto, a criação do índice e a última análise mostram a mesma data e hora. Nas versões anteriores, tínhamos que coletar estatísticas explicitamente após criarmos o índice. Saiba mais .
Em seguida, adicionaremos alguns dados e atualizaremos as estatísticas:
SQL> insert into t23 values (9999, 'TEST1')
2 /
1 row created.
SQL> insert into t23 values (-8888, 'TEST 2')
2 /
1 row created.
SQL> exec dbms_stats.gather_index_stats(user, 'I23')
PL/SQL procedure successfully completed.
SQL> select o.object_id, i.last_analyzed, i.distinct_keys
2 from user_objects o
3 join user_indexes i
4 on (i.index_name = o.object_name)
5 where o.object_type = 'INDEX'
6 and i.index_name = 'I23'
7 /
OBJECT_ID CREATED LAST_ANALYZED DISTINCT_KEYS
---------- -------------------- -------------------- -------------
116353 23-NOV-2013 00:15:39 23-NOV-2013 00:26:28 169
1 row selected.
SQL>
Agora os metadados relacionados às estatísticas mudaram, mas o índice é o mesmo objeto de banco de dados. Considerando que, se descartarmos e recriarmos o índice, obteremos um novo objeto de banco de dados:
SQL> drop index i23
2 /
Index dropped.
SQL> create index i23 on t23(id)
2 /
Index created.
SQL> select o.object_id, i.last_analyzed, i.distinct_keys
2 from user_objects o
3 join user_indexes i
4 on (i.index_name = o.object_name)
5 where o.object_type = 'INDEX'
6 and i.index_name = 'I23'
7 /
OBJECT_ID CREATED LAST_ANALYZED DISTINCT_KEYS
---------- -------------------- -------------------- -------------
116354 23-NOV-2013 00:27:50 23-NOV-2013 00:27:50 169
1 row selected.
SQL>
Em operações normais, quase nunca precisamos descartar e recriar um índice. É uma técnica que às vezes é apropriada ao carregar grandes quantidades de dados e em casos muito raros de corrupção de índice. As interwebs ainda lançam sites que recomendam a reconstrução regular de índices por motivos de desempenho (supostamente "reequilibra" índices distorcidos), mas esses sites não produzem os benchmarks para provar os benefícios a longo prazo e certamente nunca incluem o tempo e Ciclos de CPU desperdiçados pelo exercício de reconstrução.
Reconstruir um índice requer mais trabalho do que atualizar as estatísticas. Obviamente verdade, porque a reconstrução inclui a coleta de estatísticas como uma subtarefa. A questão é se é mais eficiente realizar DML em massa em uma tabela com seus índices no lugar em comparação com descartar os índices e recriá-los posteriormente. Pode ser mais rápido carregar dados em uma tabela sem índices e recriá-los posteriormente.
Não há uma regra rígida aqui:depende de quantos índices você tem, a proporção das linhas afetadas em relação ao tamanho total da tabela, se você precisa dos índices para impor restrições de integridade relacional e assim por diante. Há também uma grande diferença entre as operações:você pode querer descartar índices para inserções em massa, mas mantê-los para atualizações, dependendo de quais índices você precisa para sua cláusula WHERE e se a atualização afeta colunas indexadas.
Em suma, você precisa avaliar seu próprio cenário específico. Esta é muitas vezes a resposta quando se trata de questões de desempenho.