Как узнать, фрагментирована ли таблица в Oracle?

У меня есть стол, который, кажется, занимает больше места, чем нужно. Мне посоветовали скопировать данные в новую таблицу и переименовать новую и старую таблицы, чтобы поменять их местами. Как я могу подтвердить, что текущая таблица действительно фрагментирована? Как я могу оценить или рассчитать новый размер новой таблицы, содержащей те же данные?

3 ответа

Решение

Если ваша статистика актуальна, это должно дать достойное указание, если в таблицах гораздо больше блоков, чем предполагает объем данных строк.

select table_name, round((num_rows * avg_row_len) /(8*1024)), blocks 
from user_tables where ....

Это пространство будет использоваться для будущих вставок, поэтому не обязательно проблема. Если вы сделали большой архив или удалили данные, возможно, стоит освободить место (особенно если вы выполняете много полных сканирований таблицы). [Примечание: я предположил 8k блоков, которые по умолчанию.]

Если вы сделаете CREATE/DROP/RENAME, вы потеряете все индексы, ограничения, гранты (плюс комментарии к таблицам, если вы их используете).

Вам лучше проверить текущее табличное пространство (смотрите USER_SEGMENTS) и выполнить ALTER TABLE tablename MOVE current_tablespace;

Вам также нужно будет перестроить индексы назад. Выберите их из USER_INDEXES и сделайте ALTER INDEX ... REBUILD;

Рассмотреть возможность использования dbms_space.space_usage и другие процедуры в dbms_space пакет.

- Попробуйте запустить этот скрипт, используя svrmgrl, подключенный как администратор баз данных.

set serveroutput on

DECLARE
   libcac   NUMBER (6, 2);
   rowcac   NUMBER (6, 2);
   bufcac   NUMBER (6, 2);
   redlog   NUMBER (6, 2);
   spsize   NUMBER;
   blkbuf   NUMBER;
   logbuf   NUMBER;
BEGIN
   SELECT VALUE
     INTO redlog
     FROM v$sysstat
    WHERE name = 'redo log space requests';

   SELECT 100 * (SUM (pins) - SUM (reloads)) / SUM (pins)
     INTO libcac
     FROM v$librarycache;

   SELECT 100 * (SUM (gets) - SUM (getmisses)) / SUM (gets)
     INTO rowcac
     FROM v$rowcache;

   SELECT 100 * (cur.VALUE con.VALUE - phys.VALUE)/(cur.VALUE con.VALUE)
into bufcac
from v$sysstat cur,v$sysstat con,v$sysstat phys,
v$statname ncu,v$statname nco,v$statname nph
where cur.statistic# = ncu.statistic# and
ncu.name = 'db block gets' and
con.statistic# = nco.statistic# and
nco.name = 'consistent gets' and
phys.statistic# = nph.statistic# and
nph.name = 'physical reads';

select VALUE
into spsize
from v$parameter
where name = 'shared_pool_size';

select VALUE
into blkbuf
from v$parameter
where name = 'db_block_buffers';

select VALUE
into logbuf
from v$parameter
where name = 'log_buffer';

DBMS_OUTPUT.put_line('> SGA CACHE STATISTICS');
DBMS_OUTPUT.put_line('> ********************');
DBMS_OUTPUT.put_line('> SQL Cache Hit rate = '||libcac);
DBMS_OUTPUT.put_line('> Dict Cache Hit rate = '||rowcac);
DBMS_OUTPUT.put_line('> Buffer Cache Hit rate = '||bufcac);
DBMS_OUTPUT.put_line('> Redo Log space requests = '||redlog);
DBMS_OUTPUT.put_line('> ');
DBMS_OUTPUT.put_line('> INIT.ORA SETTING');
DBMS_OUTPUT.put_line('> ****************');
DBMS_OUTPUT.put_line('> Shared Pool Size = '||spsize||' Bytes');
DBMS_OUTPUT.put_line('> DB Block Buffer = '||blkbuf||' Blocks');
DBMS_OUTPUT.put_line('> Log Buffer = '||logbuf||' Bytes');
DBMS_OUTPUT.put_line('> ');

if libcac < 99
then
DBMS_OUTPUT.put_line('*** HINT: Library Cache too low! Increase the Shared Pool Size.');
end if;

if rowcac < 85
then
DBMS_OUTPUT.put_line('*** HINT: Row Cache too low! Increase the Shared Pool Size.');
end if;

if bufcac < 90
then
DBMS_OUTPUT.put_line('*** HINT: Buffer Cache too low! Increase the DB Block Buffer value.');
end if;

if redlog > 100
then
DBMS_OUTPUT.put_line('*** HINT: Log Buffer value is rather low!');
end if;

end;
/
Другие вопросы по тегам