Seguem minhas obs pra cada ponto : "***nós NÃO sabemos o tamanho do seu registro lógico (é uma info algo crítica que vc Não nos dá) mas tipicamente numa tabela bem compactada via de regra se vê mais registros por bloco que isso...
Desculpe, mas como pego essa informação?? " => tamanho do registro lógico é o soma total das colunas da tabela : vc pode pegar o valor médio dele na coluna AVG_ROW_LEN da DBA/ALL/USER_TABLES, ou pode calcular somando o comprimento de cada coluna, EVIDENTEMENTE com alguma imprecisão por causa das colunas de comprimento variável, como a VARCHAR2 ou NUMBER, ou mesmo por causa de LOBs/LONGS.... Porém, pra gente tentar reproduzir o seu caso e podermos palpitar melhor, seria até mais interessante vc dar o CREATE TABLE da tabela em questão (pode ser extraído Facilmente com o DBMS_METADATA.GET_DDL, veja http://www.orafaq.com/forum/mv/msg/168998/500434/102589/#msg_500434para um exemplinho) , ** E ** também dizer como essa tabela é usada, ie : se é uma tabela tipo de log de informação (portanto com INSERTs muitíssimo mais frequentes do que outros DMLs), e também o padrão de UPDATEs (ie, confirmar se a minha SUPOSIÇÃO de UPDATEs pequenos, não fazendo as colunas crescerem no caso de varchar, isso poderia levar a migração de linhas) e de que maneira os dados são deletados... A info dos DELETEs é pra identificarmos se de repente é possível que as linhas sendo deletadas estejam em blocos diferentes muitas vezes, não sendo suficientes pra que o bloco fique totalmente limpo e por isso talvez os blocos estejam com apenas essas vinte e poucas linhas... "Segue a QUERY que usei para pegar essa tabela. select tablespace_name, num_rows, table_name, round((blocks * 8) / 1024, 0) "size (mb)", round((num_rows * avg_row_len / 1024 / 1024), 0) "actual_data (mb)", (round((blocks * 8) / 1024, 0) - round((num_rows * avg_row_len / 1024 / 1024), 0)) "wasted_space (mb)" from dba_tables where (round((blocks * 8) / 1024, 0) > round((num_rows * avg_row_len / 1024 / 1024), 0)) and tablespace_name not in ('SYSTEM') order by 6 desc " ==> ok, é o que eu pensava : como havia dito, só ESPERO que ** realmente ** as estatísticas estejam o mais frescas possível, pois a NUM_ROWS só é calculada na ocasião da coleta... Essa coluna WASTED_SPACE basicamente é o espaço em bytes total dos blocos (o qual, INCLUSIVE, me parece não estar certo na query, pois se o seu block size for de 8k se deveria multiplicar BLOCKS por 8192 pra chegarmos em bytes, e não por 8, mas enfim) , e daí subtraindo o valor do registro lógico multiplicado pela qtdade de linhas - isso é uma Grossa estimativa (pois essa lógica implica que TODO o espaço dentro do bloco estaria disponível pra dados, o que NÃO é verdade - veja no manual "Database Concepts" o cap. 2 - Data Blocks, Extents, and Segments que mostra que há Sim um overhead/estruturas internas de controle), mas tá , vamos aceitar como uma Aproximação grosseira... O que eu digo em cima disso é o mesmo que disse antes, ie : até PODE ser que esteja havendo alguma ineficiência no uso do espaço interno dos blocos (é a nossa Suspeita decorrente do fato de apenas vinte e poucas linhas em média estarem em cada bloco, E a qtdade até que razoável de wasted space na estimativa acima mostrada), é investigar essa possibilidade.... Um teste bem interessante que se pode fazer é criar a estrutura da tabela Vazia (num outro database, talvez, para não causar problemas/interferência) e daí Transferir os dados pra lá : se a tabela resultante ficar melhor compactada (ie, com MAIS linhas/registros em média por bloco, e apresentando MENOS blocos no total e menos wasted space) ok, tá confirmada alguma ineficiência - pode ser migração/row chaining, pode ser o caso que citei acima de DELETEs não limpando totalmente o bloco, tem que ver o que é pra poder "consertar"... ===>>> AVISO, porém, que , como eu disse na msg anterior, essa diminuição da qtdade total de blocos vai influenciar na performance significativamente APENAS e TÃO SOMENTE se a tabela é acessada com I/O MULTIBLOCK, ie, via table scan - que fique Claro, I/O single-block via rowid vindo de índice é QUASE TOTALMENTE refratário à quantidade total de blocos.... É POR ISSO que eu perguntei na msg anterior COMO a tabela é usada, se ela for uma tabela acessada por chave, provavelmente vai ser PERDA DE TEMPO TOTAL E ABSOLUTA o trabalho de análise e "desfragmentação", ok ??? Claro ?? " ***possa valer a pena vc passar pra não-ASSM e manualmente indicar algo tipo baixo PCTFREE e PCTUSED bem alto, levando a blocos mais compactos... Vou avaliar como alterar essa tablespace conforme sua dica " => repito : isso SE e APENAS SE a tabela está sendo usada para INSERTs em qtdade MUITO MAIOR que os outrs DMLs, ie, é algum tipo de tabela de log, tá bem ??? "Irei avaliar a possibilidade de particionar a tabela conforme ja dito pelo nosso amigo Emerson" => Aviso : o particionamento reduz a quantidade total de blocos a acessar, então OBVIAMENTE só é útil para acesso que NÂO recuperem uma ou muito pouquinhas linhas, por chave, OK ?? E Óbvio#2, para que o RDBMS "saiba" que os dados estão na partição X (e portanto as n-1 outras Partições não precisam ser lidas) vc Evidentemente tem que citar a CHAVE do particionamento na query/no SQL... E lembrete : se hoje a qtdade de linhas a recuperar/acessar é grande, além de particionamento outras opções (como índice selectivo/por função, indexando só uma porção dos dados, digamos) são possíveis, OU mesmo vc pode ter uma VIEW MATERIALIZADA já com o resultado da query, Evitando ter que se acessar a tabela grande todinha ou quase todinha como hoje é feito, se é feito... []s Chiappa