Para melhor visualização, recomendo resolução de no mínimo 1280 x 800 e navegador Mozilla Firefox


sexta-feira, 4 de fevereiro de 2011

Executando operações de manutenção em tabelas particionadas no Oracle ...

Por Eduardo Legatti

Olá,

Sabemos que o particionamento é uma técnica que permite que as tabelas e índices sejam divididos em componentes menores e mais gerenciáveis dentro de um banco de dados. As tabelas particionadas ajudam a tornar o banco de dados mais disponível e de melhor manutenção pelo fato de cada partição poder ser criada em tablespaces distintos. Por algumas razões de desempenho, cada partição de uma tabela pode e deve residir na sua própria tablespace. Uma outra vantagem é que as tabelas particionadas podem também melhorar o desempenho de consultas, pois quando uma operação de consulta é efetuada sobre uma tabela particionada, o otimizador determina a partição envolvida – característica denominada de Partition Pruning, desde que a operação esteja condicionada pela chave de partição.

Vale a pena salientar que o particionamento é transparente para as aplicações e não é necessária nenhuma alteração nas instruções SQL para tirar vantagem dele. No entanto, podem haver situações onde especificar uma partição diretamente na instrução SQL seria vantajoso. No mais, o objetivo deste artigo será apresentar de forma mais didática e, para quem já conhece um pouco sobre particionamento, algumas das operações básicas que podemos realizar nas partições de uma tabela particionada. Dentre algumas das operações temos: RENAME, MERGE, SPLIT, TRUNCATE, DROP, ADD, EXCHANGE, ANALYZE e MOVE. Para início, irei criar uma tabela de exemplo simples chamada T1. No caso, usarei o método range partition que foi um dos primeiros métodos de particionamento criado pela Oracle e existente desde a versão do Oracle 8.
 
C:\>sqlplus scott/tiger

SQL*Plus: Release 10.2.0.1.0 - Production on Sex Fev 4 12:47:28 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Conectado a:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> create table t1
  2    (id  number)
  3     tablespace users
  4     partition by range(id)
  5      (
  6       partition pdezenas  values less than (100)  tablespace tbs_dezenas,
  7       partition pcentenas values less than (1000) tablespace tbs_centenas,
  8       partition pmilhares_1000 values less than (2000)  tablespace tbs_milhares,
  9       partition pmilhares_2000 values less than (3000)  tablespace tbs_milhares,
 10       partition pmilhares_3000 values less than (4000)  tablespace tbs_milhares,
 11       partition pmilhares_4000 values less than (5000)  tablespace tbs_milhares,
 12       partition pmilhares_n values less than (maxvalue) tablespace tbs_milhares
 13    );

Tabela criada.

SQL> create index idx_t1_id on t1 (id) local tablespace tbs_indx;

Índice criado.

SQL> insert into t1 select level from dual connect by level <= 10000;

10000 linhas criadas.

SQL> exec dbms_stats.gather_table_stats('SCOTT','T1');

Procedimento PL/SQL concluído com sucesso.
 
Com os comandos acima, eu criei uma tabela particionada T1 com apenas uma coluna para fins de demonstração e a populei com 10 mil registros. Foi criado também um índice particionado localmente. Um índice particionado local é muito simples de configurar e manter porque o seu esquema de particionamento é idêntico ao esquema da tabela base. Em outras palavras, o número de partições do índice é igual ao número de partições da tabela. Para um fácil entendimento, eu criei 7 partições que armazenam números. A partição pdezenas foi criada na tablespace tbs_dezenas, a partição pcentenas foi criada na tablespace tbs_centenas e, as partições restantes, na tablespace tbs_milhares. Abaixo irei executar algumas instruções SQL para obter algumas informações pertinentes sobre a tabela particionada T1.

SQL> select table_name,
  2         partitioning_type,
  3         partition_count,
  4         def_tablespace_name
  5    from user_part_tables;

TABLE_NAME     PARTITI PARTITION_COUNT DEF_TABLESPACE_NAME
-------------- ------- --------------- -------------------
T1              RANGE                7 USERS

Utilizando a view de dicionário de dados USER_PART_TABLES, acima podemos ver que a tabela foi particionada pelo método RANGE e que a mesma possui atualmente 7 partições.

SQL> select index_name,
            table_name,
            partitioning_type,
            locality,
            alignment
       from user_part_indexes;

INDEX_NAME     TABLE_NAME       PARTITI  LOCALI  ALIGNMENT
-------------- ---------------- -------- ------- ---------
IDX_T1_ID      T1               RANGE    LOCAL   PREFIXED


Utilizando a view de dicionário de dados USER_PART_INDEXES, acima podemos ver que o índice IDX_T1_ID também foi particionado pelo método RANGE e que o mesmo é um índice LOCAL.

SQL> select * from USER_PART_KEY_COLUMNS;

NAME        OBJEC     COLUMN_NAME  COLUMN_POSITION
----------- --------  ------------ ---------------
T1          TABLE     ID                         1
IDX_T1_ID   INDEX     ID                         1

Utilizando a view de dicionário de dados USER_PART_KEY_COLUMNS, acima podemos obter a coluna chave da partição. Abaixo a coluna PARTITIONED da view USER_TABLES nos mostra que a tabela T1 é uma tabela particionada.
 
SQL> select table_name,partitioned,num_rows from user_tables;

TABLE_NAME           PAR   NUM_ROWS
-------------------- --- ----------
T1                   YES      10000

Abaixo irei executar uma instrução SQL para obter da view USER_TAB_PARTITIONS algumas informações sobre os nomes das partições e o número de linhas em cada partição.

SQL> break on report
SQL> compute sum of num_rows on report
SQL> select table_name,
  2         partition_name,
  3         high_value,
  4         num_rows
  5  from user_tab_partitions;

TABLE_NAME  PARTITION_NAME   HIGH_VALUE NUM_ROWS
----------- ---------------- ---------- ---------
T1          PDEZENAS         100               99
T1          PCENTENAS        1000             900
T1          PMILHARES_1000   2000            1000
T1          PMILHARES_2000   3000            1000
T1          PMILHARES_3000   4000            1000
T1          PMILHARES_4000   5000            1000
T1          PMILHARES_N      MAXVALUE        5001
                                        ---------
sum                                         10000

7 linhas selecionadas.

Vale a pena salientar que podemos também acessar diretamente os dados de uma partição como mostrado no exemplo abaixo:

SQL> select count(*) from t1 partition (pdezenas);

  COUNT(*)
----------
        99

Uma curiosidade. Cada partição de tabela e índice é um segmento como mostrado na saída do SQL abaixo. Acessando a view USER_SEGMENTS, podemos ver os segmentos em suas tablespaces correspondentes.

SQL> select segment_name,
 2          partition_name,
 3          segment_type,
 4          tablespace_name 
 5     from user_segments;

SEGMENT_NAME  PARTITION_NAME    SEGMENT_TYPE       TABLESPACE_NAME
------------- ----------------- ------------------ ---------------
T1            PDEZENAS          TABLE PARTITION    TBS_DEZENAS
T1            PCENTENAS         TABLE PARTITION    TBS_CENTENAS
T1            PMILHARES_1000    TABLE PARTITION    TBS_MILHARES
T1            PMILHARES_2000    TABLE PARTITION    TBS_MILHARES
T1            PMILHARES_3000    TABLE PARTITION    TBS_MILHARES
T1            PMILHARES_4000    TABLE PARTITION    TBS_MILHARES
T1            PMILHARES_N       TABLE PARTITION    TBS_MILHARES
IDX_T1_ID     PDEZENAS          INDEX PARTITION    TBS_INDX
IDX_T1_ID     PCENTENAS         INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_1000    INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_2000    INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_3000    INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_4000    INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_N       INDEX PARTITION    TBS_INDX

14 linhas selecionadas.

Podemos perceber acima que, por padrão, as partições de índices recebem o mesmo nome das partições de tabela. Bom, agora irei demonstrar algumas operações básicas que poderemos realizar nas partições em si.


----------------
RENAME PARTITION
----------------


Renomear uma partição é bem simples. Para que fique visualmente mais elegante, irei renomear todas partições de índice de forma que o nome fique diferente das partições de tabela.

SQL> alter index IDX_T1_ID rename partition PDEZENAS to PDEZENAS_INDX;

Índice alterado.

SQL> alter index IDX_T1_ID rename partition PCENTENAS to PCENTENAS_INDX;

Índice alterado.

SQL> alter index IDX_T1_ID rename partition PMILHARES_1000 to PMILHARES_1000_INDX;

Índice alterado.

SQL> alter index IDX_T1_ID rename partition PMILHARES_2000 to PMILHARES_2000_INDX;

Índice alterado.

SQL> alter index IDX_T1_ID rename partition PMILHARES_3000 to PMILHARES_3000_INDX;

Índice alterado.

SQL> alter index IDX_T1_ID rename partition PMILHARES_4000 to PMILHARES_4000_INDX;

Índice alterado.

SQL> alter index IDX_T1_ID rename partition PMILHARES_N to PMILHARES_N_INDX;

Índice alterado.


Após a execução dos comandos acima, podemos ver abaixo que as partições de índice foram renomeadas.

SQL> select segment_name,
  2         partition_name,
  3         segment_type,
  4         tablespace_name
  5  from  user_segments
  6  where segment_type = 'INDEX PARTITION';

SEGMENT_NAME  PARTITION_NAME       SEGMENT_TYPE       TABLESPACE_NAME
------------- -------------------- ------------------ ---------------
IDX_T1_ID     PDEZENAS_INDX        INDEX PARTITION    TBS_INDX
IDX_T1_ID     PCENTENAS_INDX       INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_1000_INDX  INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_2000_INDX  INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_3000_INDX  INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_4000_INDX  INDEX PARTITION    TBS_INDX
IDX_T1_ID     PMILHARES_N_INDX     INDEX PARTITION    TBS_INDX

7 linhas selecionadas.
 
---------------
MERGE PARTITION
---------------


Uma operação de MERGE significa mesclar ou combinar duas partições em uma só. No exemplo abaixo irei mesclar as partições PMILHARES_1000 e PMILHARES_2000 em uma nova partição que chamarei intencionalmente também de PMILHARES_2000. A operação de MERGE dropa as duas partições em questão e cria uma nova.

SQL> alter table t1 merge partitions
  2  PMILHARES_1000,
  3  PMILHARES_2000
  4  into partition PMILHARES_2000 tablespace tbs_milhares;

Tabela alterada.

SQL> select segment_name,
 2          partition_name,
 3          segment_type,
 4          tablespace_name 
 5     from user_segments
 6     where segment_type='TABLE PARTITION';

SEGMENT_NAME  PARTITION_NAME    SEGMENT_TYPE       TABLESPACE_NAME
------------- ----------------- ------------------ ---------------
T1            PDEZENAS          TABLE PARTITION    TBS_DEZENAS
T1            PCENTENAS         TABLE PARTITION    TBS_CENTENAS
T1            PMILHARES_2000    TABLE PARTITION    TBS_MILHARES
T1            PMILHARES_3000    TABLE PARTITION    TBS_MILHARES
T1            PMILHARES_4000    TABLE PARTITION    TBS_MILHARES
T1            PMILHARES_N       TABLE PARTITION    TBS_MILHARES

6 linhas selecionadas.


No resultado do SQL acima, podemos ver que a partição PMILHARES_1000 não existe mais. Vale a pena salientar que será necessário reconstruir o índice da nova partição criada como demonstrado no exemplo abaixo:

SQL> exec dbms_stats.gather_table_stats('SCOTT','T1');
BEGIN dbms_stats.gather_table_stats('SCOTT','T1'); END;
*
ERRO na linha 1:
ORA-20000: index "SCOTT"."IDX_T1_ID"  or partition of such index is in unusable state
ORA-06512: em "SYS.DBMS_STATS", line 13056
ORA-06512: em "SYS.DBMS_STATS", line 13076
ORA-06512: em line 1

SQL> select index_name,
 2          partition_name,
 3          high_value 
 4     from user_ind_partitions where status='UNUSABLE';

INDEX_NAME  PARTITION_NAME      HIGH_VALUE STATUS
----------- ------------------- ---------- --------
IDX_T1_ID   PMILHARES_2000_INDX 3000       UNUSABLE

SQL> alter table t1 modify partition PMILHARES_2000 rebuild unusable local indexes;

Tabela alterada.

SQL> exec dbms_stats.gather_table_stats('SCOTT','T1');

Procedimento PL/SQL concluído com sucesso.

---------------
SPLIT PARTITION
---------------


Dividir uma partição em duas também é bem simples. No exemplo abaixo, irei dividir a partição PMILHARES_N de forma a manter a partição PMILHARES_N e criar uma nova partição PMILHARES_5000.

SQL> select table_name,
 2          partition_name,
 3          num_rows
 4     from user_tab_partitions where partition_name='PMILHARES_N';

TABLE_NAME     PARTITION_NAME       NUM_ROWS
-------------- ------------------ ----------
T1             PMILHARES_N              5001

SQL> alter table t1 split partition
  2  PMILHARES_N at (6000)
  3  into (partition PMILHARES_5000,
  4        partition PMILHARES_N);

Tabela alterada.

Assim como na operação de MERGE, será necessário recontruir os índices das partições envolvidas.

SQL> select index_name,
            partition_name,
            high_value 
       from user_ind_partitions where status='UNUSABLE';

INDEX_NAME  PARTITION_NAME      HIGH_VALUE STATUS
----------- ------------------- ---------- --------
IDX_T1_ID   PMILHARES_5000      6000       UNUSABLE
IDX_T1_ID   PMILHARES_N_INDX    MAXVALUE   UNUSABLE

SQL> alter table t1 modify partition PMILHARES_5000 rebuild unusable local indexes;

Tabela alterada.

SQL> alter table t1 modify partition PMILHARES_N rebuild unusable local indexes;

Tabela alterada.

Bom, de acordo com o resultado do SQL abaixo, o esquema da tabela T1 após a operação de SPLIT ficou assim:

SQL> break on report
SQL> compute sum of num_rows on report
SQL> select table_name,
  2         partition_name,
  3         high_value,
  4         num_rows
  5  from user_tab_partitions;

TABLE_NAME  PARTITION_NAME   HIGH_VALUE NUM_ROWS
----------- ---------------- ---------- ---------
T1          PDEZENAS         100               99
T1          PCENTENAS        1000             900
T1          PMILHARES_2000   3000            2000
T1          PMILHARES_3000   4000            1000
T1          PMILHARES_4000   5000            1000
T1          PMILHARES_5000   6000            1000
T1          PMILHARES_N      MAXVALUE        4001
                                        ---------
sum                                         10000

------------------
TRUNCATE PARTITION
------------------


Truncar uma partição não é diferente de truncar uma tabela não particionada.

SQL> alter table t1 truncate partition PMILHARES_N;

Tabela truncada.

SQL> break on report
SQL> compute sum of num_rows on report
SQL> select table_name,
  2         partition_name,
  3         high_value,
  4         num_rows
  5  from user_tab_partitions;

TABLE_NAME  PARTITION_NAME   HIGH_VALUE NUM_ROWS
----------- ---------------- ---------- ---------
T1          PDEZENAS         100               99
T1          PCENTENAS        1000             900
T1          PMILHARES_2000   3000            2000
T1          PMILHARES_3000   4000            1000
T1          PMILHARES_4000   5000            1000
T1          PMILHARES_5000   6000            1000
T1          PMILHARES_N      MAXVALUE           0
                                        ---------
sum                                          5999

Podemos perceber que após a execução do comando TRUNCATE PARTITION na partição PMILHARES_N, a mesma teve os seus dados apagados.


--------------

DROP PARTITION
--------------


Dropar uma partição também não é diferente de dropar uma tabela não particionada.

SQL> alter table t1 drop partition PMILHARES_N;

Tabela alterada.

SQL> break on report
SQL> compute sum of num_rows on report
SQL> select table_name,
  2         partition_name,
  3         high_value,
  4         num_rows
  5  from user_tab_partitions;

TABLE_NAME  PARTITION_NAME   HIGH_VALUE NUM_ROWS
----------- ---------------- ---------- ---------
T1          PDEZENAS         100               99
T1          PCENTENAS        1000             900
T1          PMILHARES_2000   3000            2000
T1          PMILHARES_3000   4000            1000
T1          PMILHARES_4000   5000            1000
T1          PMILHARES_5000   6000            1000
                                        ---------
sum                                          5999

Podemos perceber que após a execução do comando DROP PARTITION na partição PMILHARES_N, a mesma não existe mais.


-------------
ADD PARTITION
-------------


Adicionar uma partição é bem simples. Veja o exemplo abaixo:

SQL> insert into t1 values (6500);
insert into t1 values (6500)
            *
ERRO na linha 1:
ORA-14400: chave de partição inserida não está mapeada para partição alguma

Ao tentar inserir o registro 6500, o erro ORA-14400 foi emitido pelo fato da chave de partição inserida não está mapeada para nenhuma partição. Neste caso, irei criar uma nova partição chamada de PMILHARES_6000 que poderá armazenar valores até o número 7000.

SQL> alter table t1
  2  add partition PMILHARES_6000
  3  values less than (7000) tablespace tbs_milhares;

Tabela alterada.

Após a criação da partição, poderemos inserir o registro sem maiores problemas como demonstrado no comando abaixo:

SQL> insert into t1 values (6500);

1 linha criada.

SQL> commit;

Commit concluído.

SQL> exec dbms_stats.gather_table_stats('SCOTT','T1');

Bom, após a criação da nova partição, podemos verificar como ficou o esquema de partições da tabela T1.

SQL> break on report
SQL> compute sum of num_rows on report
SQL> select table_name,
  2         partition_name,
  3         high_value,
  4         num_rows
  5  from user_tab_partitions;

TABLE_NAME  PARTITION_NAME   HIGH_VALUE NUM_ROWS
----------- ---------------- ---------- ---------
T1          PDEZENAS         100               99
T1          PCENTENAS        1000             900
T1          PMILHARES_2000   3000            2000
T1          PMILHARES_3000   4000            1000
T1          PMILHARES_4000   5000            1000
T1          PMILHARES_5000   6000            1000
T1          PMILHARES_6000   7000               1
                                        ---------
sum                                          6000

------------------
EXCHANGE PARTITION
------------------


O comando EXCHANGE PARTITION é um método bem eficiente de realocar um segmento de tabela não particionada para uma tabela particionada. Poderemos perceber que o procedimento será muito mais rápido do que que realizar um INSERT na tabela. Vale a pena salientar que este recurso permite tanto mover o segmento de uma tabela não particionada para uma tabela particionada como o contrário. Para realizar esta demonstração irei criar uma tabela T2 com aproximadamente 10 milhões de registros. Primeiro irei recriar a partição PMILHARES_N com MAXVALUE para pode acomodar os registros que virão do segmento T2.

SQL> alter table t1 add partition PMILHARES_N
  2  values less than (maxvalue)
  3  tablespace tbs_milhares;

Tabela alterada.

Agora irei criar a tabela T2 com aproximadamente 10 milhões de registros.

SQL> create table t2
  2  tablespace tbs_milhares
  3  as
  4  select id from (select level id
  5                  from dual
  6                  connect by level <=10000000)
  7            where id >= 7000;

Tabela criada.

SQL> select count(*) from t2;

  COUNT(*)
----------
   9993001

Agora irei simular a inserção dos dados na tabela T1 provenientes da tabela T2 utilizando um INSERT SELECT.

SQL> set timing on
SQL> insert into t1 select * from t2;

9993001 linhas criadas.

Decorrido: 00:02:21.64

Podemos perceber que a operação executou em 2 minutos e 21 segundos. Agora irei limpar os dados da partição e utilizar o método EXCHANGE PARTITION de forma a transferir os dados da tabela T2 para a tabela T1:

SQL> set timing off
SQL> alter table t1 truncate partition PMILHARES_N;

Tabela truncada.

SQL> set timing on
SQL> alter table t1
  2  exchange partition PMILHARES_N
  3  with table t2;

Tabela alterada.

Decorrido: 00:00:12.11

Podemos perceber acima que a operação foi executada em aproximadamente 12 segundos, ou seja, nem se compara com o método INSERT SELECT.

SQL> set timing off
SQL> select count(*) from t2;

  COUNT(*)
----------
         0

No mais, podemos perceber que após a operação, os dados na tabela T2 não existem mais, pois os mesmos foram movidos para a tabela T1. Abaixo, da mesma forma que outras operações, teremos também que reconstruir o índice da partição que sofreu a operação de EXCHANGE.

SQL> exec dbms_stats.gather_table_stats('SCOTT','T1');
BEGIN dbms_stats.gather_table_stats('SCOTT','T1'); END;
*
ERRO na linha 1:
ORA-20000: index "SCOTT"."IDX_T1_ID"  or partition of such index is in unusable state
ORA-06512: em "SYS.DBMS_STATS", line 13056
ORA-06512: em "SYS.DBMS_STATS", line 13076
ORA-06512: em line 1

SQL> select index_name,
  2         partition_name,
  3         high_value
  4    from user_ind_partitions where status='UNUSABLE';

INDEX_NAME  PARTITION_NAME      HIGH_VALUE STATUS
----------- ------------------- ---------- --------
IDX_T1_ID   PMILHARES_N         MAXVALUE   UNUSABLE

SQL> alter table t1 modify partition PMILHARES_N rebuild unusable local indexes;

Tabela alterada.


Após as operações realizadas acima, temos abaixo o esquema atual das partições da tabela T1.

SQL> break on report
SQL> compute sum of num_rows on report
SQL> select table_name,
  2         partition_name,
  3         high_value,
  4         num_rows
  5  from user_tab_partitions;

TABLE_NAME  PARTITION_NAME   HIGH_VALUE NUM_ROWS
----------- ---------------- ---------- ---------
T1          PDEZENAS         100               99
T1          PCENTENAS        1000             900
T1          PMILHARES_2000   3000            2000
T1          PMILHARES_3000   4000            1000
T1          PMILHARES_4000   5000            1000
T1          PMILHARES_5000   6000            1000
T1          PMILHARES_6000   7000               1
T1          PMILHARES_N      MAXVALUE     9993001
                                        ---------
sum                                       9999001

-----------------
ANALYZE PARTITION
-----------------


Da mesma forma que podemos coletar estatísticas em uma tabela não particionada, poderemos também coletar estatísticas individualmente de partições como demonstrado abaixo:

SQL> analyze table t1 partition (PMILHARES_N) compute statistics;

Tabela analisada.

SQL> select table_name,
 2          partition_name,
 3          last_analyzed,
 4          num_rows 
 5     from user_tab_partitions
 6    where partition_name='PMILHARES_N';

TABLE_NAME    PARTITION_NAME     LAST_ANALY   NUM_ROWS
------------- ------------------ ---------- ----------
T1            PMILHARES_N        04/02/2011    9993001

--------------
MOVE PARTITION
--------------


Por fim, da mesma forma que podemos mover uma tabela não particionada para outra tablespace, poderemos também mover uma partição específica para outra tablespace. Na demonstração abaixo, a partição PDEZENAS se encontra na tablespace TBS_DEZENAS.

SQL> select table_name,
 2          partition_name,
 4          tablespace_name
 4    where partition_name='PDEZENAS';

TABLE_NAME     PARTITION_NAME      TABLESPACE_NAME
-------------- ------------------- ---------------
T1             PDEZENAS            TBS_DEZENAS


Irei mover a partição PDEZENAS para a tablespace TBS_CENTENAS fazendo uso do comando MOVE PARTITION.

SQL> alter table t1 move partition PDEZENAS tablespace TBS_CENTENAS;

Tabela alterada.

SQL> select table_name,
 2          partition_name,
 4          tablespace_name
 4    where partition_name='PDEZENAS';

TABLE_NAME     PARTITION_NAME      TABLESPACE_NAME
-------------- ------------------- ---------------
T1             PDEZENAS            TBS_CENTENAS


Assim como nas tabelas não particionadas, sempre após o comando MOVE, deveremos reconstruir o índice. Neste caso, irei reconstruir o índice da partição PDEZENAS.

SQL> alter table t1 modify partition PDEZENAS rebuild unusable local indexes;

Tabela alterada.

No mais, dependendo das operações DDL executadas nas partições da tabela (ADD, DROP, MOVE, TRUNCATE, SPLIT, MERGE, EXCHANGE ...) os índices da tabela poderão ficar inutilizáveis e precisarem ser reconstruídos. Geralmente, um índice global caso exista na tabela, poderá ficar marcado como inutilizável (unusable). Portanto, utilizar a cláusula UPDATE GLOBAL INDEXES é uma boa prática:

SQL> ALTER TABLE ... DROP PARTITION P1 UPDATE GLOBAL INDEXES;
SQL> TRUNCATE TABLE ... UPDATE GLOBAL INDEXES;
SQL> ALTER TABLE ... DROP PARTITION P1 UPDATE GLOBAL INDEXES;




11 comentários:

David Siqueira disse...

Fala grande parceiro!!!

É chover no molhado qualquer elogio a este POST, não é a toa que logo logo tu será com certeza um futuro ACE Latin America, um grande abraço meu amigo.
Muito Sucesso!
Excelente POST!!!!

Eduardo Legatti disse...

Olá David,

Obrigado pelo comentário. Pode deixar que ainda eu chego lá ;-)

Abraços e até mais ...

Marcelo P Vargas disse...

Parabéns Eduardo,
Tenho algumas tabelas particionadas na base aqui do trabalho e estava com algumas dúvidas... e esse seu artigo não tirou a minha dúvida, simplesmente foi uma aula completa. Muito prático e bem elaborado.
Excelente artigo.

Eduardo Legatti disse...

Olá Marcelo,

Obrigado pelo comentário.

Abraços e até mais ...

Bruno Apocalypse disse...

Olá. Estou procurando aprender um pouco mais sobre particionamentos. Realmente uma aula IMPRESSIONANTE. Seu blog já entrou nos favoritos. Obrigado.

Fábio Prado disse...

Eduardo, ótimo artigo!

[]s

Fábio Prado
www.fabioprado.net

Anônimo disse...

Olá Eduardo.
Parabéns pelo post. Muito bem explicado e de grande utilidade. Mas tenho uma dúvida: Acredito que o recurso de particionamento de tabelas existe somente na versão Enterprise do Oracle, você saberia se é possível fazer algo do tipo na versão Standard?

Eduardo Legatti disse...

Olá Denis,

A feature de particionamento é uma option disponível somente na edição Enterprise :-( Se você quiser particionar uma tabela na versão Standard, então terá que utilizar métodos nada convencionais como, por exemplo, criar tabelas com estruturas iguais com nomes diferentes. Uma tabela PEDIDO, por exemplo, seria dividida em PEDIDO_2010, PEDIDO_2011, PEDIDO_2012, etc. Neste caso você teria que utilizar views de banco de dados para unir os registros dessas tabelas. Não sei se valeria a pena, pois isso poderá impactaria em alteração de código da aplicação.

Abraços

Legatti

Unknown disse...

Caramba, SHOW DE BOLA!

Muito bem detalhado e prático, foi para o meu favoritos rs, parabéns!

Eduardo Legatti disse...

Olá Arilson,

Obrigado pela visita!

Abraços,

Legatti

Unknown disse...

Excelente didatica parabéns!!

Postagens populares