Ok... Bom, a primeira pergunta que te faço é : vc TEM CERTEZA que as tabelas 
que "seguram" o espaço que hoje está em branco/não está em uso mas reservado  
** REALMENTE ** nunca mais vão sofrer carga de dados ??? O ponto aqui é que 
NATURALMENTE o espaço sem uso mas reservado VAI SIM ser reusado automagicamente 
nos próximos INSERTs (INSERTs normais, em não-append mode) : se depois de todo 
o trabalho acontecer de vc não sabia que semana que vem vai haver uma carga 
grande de dados aí as tabelas crescem tudo de novo, foi INÚTIL o seu trabalho 
todo ... Yep ??
  Segunda pergunta :  vc quer/precisa que esse espaço hoje sem uso mas 
reservado REALMENTE seja devolvido ao Sistema Operacional (para ser usado 
alhures) OU simplesmente ter esse espaço constando na DBA_FREE_SPACE dessa 
mesma tablespace (e portanto podendo ser reusado por qquer Segmento dessa 
tablespace) ?? Pois se for necessário devolver o espaço ao SO (via RESIZE do 
datafile, deleção do datafile, etc) realmente vc precisará MOVER os blocos, mas 
se vc ter esse espaço (ou a maior parte dele) disponível como FREE para essa 
tablespace já resolve, vc ** PODE SIM ** usar o SHRINK mas com a opção COMPACT 
depois de ter inserido nalgum outro lugar os dados que quer salvar e feito o 
TRUNCATE das tabelas envolvidas : veja  
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:153612348067 
como ref.... Esse link mostra SIM que é Totalmente possível se liberar espaço 
via SHRINK mesmo com blocos em branco no meio..
  
  Só mesmo se REALMENTE vc precisa diminuir fisicamente os datafiles é que vc 
vai ter que apelar para o Procedimento que vc descreve, e com as seguintes 
ressalvas :
  
 " 
 1) criar uma tablespace nova xxx_dados_aud;
 2) criar 5 tabelas novas na xxx_dados_aud idênticas as tabelas que eu preciso 
deletar(PK/FK/Index etc criados no final do processo de insert);
 3) fazer insert nas tabelas novas a partir de um select nas tabelas antigas, 
copiando todos os dados que eu necessito manter no banco;
 "
 

 ==> iirc vc tá usando a Standard Edition, onde não há Parallel SQL, então esse 
INSERT não poderá ser paralelizado E a busca dos dados a serem salvos/inseridos 
nas tabs de trabalho também não poderá ser paralelizado: vc TEM que usar então 
INSERT em APPEND-MODE, BULK ARRAY, Paralelismo DIY e etc onde possível 
 

 

 "
 4) Após dados copiados para as novas tabelas, dar um truncate/drop nas tabelas 
antigas;  
 "
 

 ==> Muito certamente TEM que ser TRUNCATE, pois como dito anteriormente com o 
DROP vc PERDE as contsraints, permissões/grants que haviam sido feitas 
anteriormente, perde os objetos secundários da tabela (como ÍNDICES).... OK ? E 
muito provavelmente vc terá que DESABILITAR temporariamente as FKs 
relacionadas, pois o RDBMS  não deixa vc fazer TRUNCATE com FKs habilitadas.
  Este último ponto é importante : enquanto vc estiver com as FKs 
desabilitadas, ÓBVIO que vc não vai deixar as aplicações fazerem DMLs, pois 
podem entrar dados inválidos : pra isso vc vai ter que aplicar manualmente um 
LOCK nas tabelas e/ou temporariamente revokar os privs de DMLs.. Tecnicamente 
pra consulta tudo bem (já que a ESTRUTURA das tabelas, ie, colunas/datatypes, 
não está mudando) - só o que vai acontecer é que os dados que foram Consultados 
antes do TRUNCATE ** obviamente ** não mais estarão presentes depois dele para 
serem localizados e alterados, mas a Query que estiver rodando não vai ter 
problemas...
  
 "
 5) Renomear as novas tabelas, criadas no passo 2, para o mesmo nome das 
tabelas antigas, e todas as suas referencias,
 "
 

 => Não : justamente pra não ter que se preocupar com referências, a idéia é 
inserir (em append-mode e do jeito mais rápido possível) os dados que estão nas 
tabelas xxx_aud nas tabelas xxx originais que estão VAZIAS, e depois aí sim SE 
necessário mesmo o RESIZE, aí vc move essas tabelas que eram grandes mas que 
agora estão com POUCOS dados
 

 

 "
 5) Criar outra tablespace xxx_dados2;
 6) Mover as outras 62 tabelas para a segunda tablespace criada xxx_dados2;
 7) dropar a tablespace antiga, xxx_dados;
 8) Renomear a tablespace xxx_dados2 e seus datafiles para o mesmo nome da 
tablespace antiga;
 "
 

 => Aqui ficou uma dúvida : essas 62 tabelas (que são pequenas, pelo que 
entendi) não precisam sofrer qquer tipo de DELETE, correto ? Se sim OK, em 
sendo necessário o RESIZE do datafile vc as vai mover.... 
  Observo apenas que, se for Enterprise Edition, o database já permite que essa 
movimentação seja feita ONLINE, mas se for Standard Edition aí não..
  
 "O que estou pensando em fazer, é realizar o move das tabelas de forma 
gradativa, sem parar as aplicações 
 na madrugada. Pois na madrugada o acesso as aplicações são poucas e se a 
aplicação tentar acessar a tabela que esta sendo movida, a mesma ira estar 
locada. Desta forma meu dowtime seria menor.
 

 O meu medo é que corrompa algo no momento do move, com as aplicações tentando 
acessar a tabela em movimento, mesmo tendo o lock de DML quando se realiza o 
move da tabela.
 Porém para que eu faça isso com as aplicações no ar, tenho que ter a certeza 
de que a rotina da aplicação não ira perder nenhum dado, após tentar acessar a 
tabela em movimento e não conseguir.
 "
 

 Repito : afaik vc só poderá fazer mover segmento pra outa tablespace (seja o 
MOVE de tabela, REBUILD de índices ou a redefinição via DBMS_REDEFINE) online, 
sem indisponibilidade NEM para consulta NEM para DMLs) SE a apenas SE vc 
estiver usando RDBMS Enterprise Edition, pois ele cria uma tabela "stage" que 
vai acumular os DMLs havidos enquanto a redefinição tá rolando... 
  Caso vc esteja na Standard, vc vai ter que usar as opções OFFLINE de 
MOVE/REBUILD/Redefinição, e o que acontece com elas é que (justamente para 
EVITAR a chance de que novas linhas sejam adicionadas na tablespace antiga 
enquanto o MOVE tá rolando) o RDBMS aplica um LOCK EXCLUSIVO a nível de tabela 
(NÂO é LOCK de linhas, de DMLs : é um lock acima, que sim bloqueia DMLs mas 
Também outras alterações)...
 Então as eventuais Consultas vão acontecer naturalmente mas DMLs não... Então 
Não tem a menor chance de "algo se corromper" , o RDBMS Oracle é um tanto mais 
seguro que isso, e todos os mecanismos de lock/controle multiusuário/alterações 
de estruturas já foi mais que testado nesses mais de 20 anos em que o RDBMS 
Oracle existe...
 

 []s
 

   Chiappa
 

Responder a