Oracle: как узнать место хранения таблицы?

Ответы:

17

Через OEM 10 г,

  1. Подключитесь к базе данных как обычно
  2. Нажмите на Schemaвкладку
  3. По Tablesссылке в базе данных объектов
  4. Введите имя схемы и имя объекта (необязательно) и нажмите Go
  5. Используйте переключатель, чтобы выбрать таблицу, на которую хотите посмотреть, и нажмите Edit (не нажимайте на ссылку с именем таблицы).
  6. Нажмите на Segmentsвкладку (и подождите ...)
  7. Вы увидите размер данных таблицы и используемых индексов.

Хорошо, что технически ответил на ваш вопрос. Но лучший способ это:

  1. Вход в систему с использованием SQLPLUS
  2. Запустите скрипт от Винсента.

Мне нравится сохранять сценарий как t.sqlкраткий справочник

COLUMN size_mb      FORMAT '999,999,990.0'
COLUMN num_rows     FORMAT '999,999,990'
COLUMN fmt_short    FORMAT A24


COLUMN owner        FORMAT A16
COLUMN table_name   LIKE fmt_short
COLUMN tablespace_name  LIKE fmt_short

SET LINESIZE 200
SET AUTOTRACE OFF

COMPUTE SUM OF size_mb ON REPORT
BREAK ON REPORT

SELECT 
    lower( owner )      AS owner
    ,lower(table_name)  AS table_name
    ,tablespace_name
    ,num_rows
    ,blocks*8/1024      AS size_mb
    ,pct_free
    ,compression 
    ,logging
FROM    all_tables 
WHERE   owner           LIKE UPPER('&1')
OR  owner           = USER
ORDER BY 1,2;

CLEAR COMPUTES
CLEAR BREAKS
парень
источник
12

Пространство, используемое таблицей, является пространством, используемым всеми ее экстентами:

SELECT SUM(bytes), SUM(bytes)/1024/1024 MB
    FROM dba_extents
    WHERE owner = :owner
    AND segment_name = :table_name;

SUM(BYTES)         MB
---------- ----------
3066429440   2924,375
Винсент
источник
Не уверен, что это будет работать, потому что он не учитывает индексы, не так ли?
Кодек
1
@Codek: правильно, это только пространство, используемое самой таблицей. Однако вы можете рассчитать пространство, используемое индексами, тем же методом (поскольку индексы являются сегментами и имеют экстенты).
Винсент
на самом деле - это просто хитрее, так как «имя» индекса может быть чем угодно!
Кодек
1
Это работает только для таблиц, в которых нет столбцов больших объектов.
pacoverflow
@pacoverflow хорошая точка !
Винсент
8

Вы уверены, что оригинальный подход с использованием представления all_tables включает экстенты больших объектов? Я бы подумал, что нет. Вот то, что я считаю полезным:

with da as (
 SELECT owner, segment_name, SUM(bytes)/1024/1024 size_mb
   FROM dba_extents
   group by rollup(owner, segment_name)
) select owner, segment_name, size_mb, round(size_mb/total_mb*100)
  from da 
    cross join (
      select size_mb as total_mb 
      from da t where owner is null and segment_name is null
    )
order by size_mb desc

Это показывает мне, что использует больше всего места.

Гюнтер Шадов
источник
2

После некоторых поисков и экспериментов в Google я создал следующий запрос, который, на мой взгляд, дает наиболее точный результат. Для пользователя-оракула он предоставляет свободное / использованное / общее пространство по таблицам и типам сегментов (TABLE *, INDEX *, LOB *). Вы можете легко расширить его, чтобы предоставить дополнительную статистику, такую ​​как количество блоков.

Типичный результат:

table    ; segment type  ; used (mb) ; unused (mb) ;  total (mb)
user     ; INDEX         ;       0,78;         0,00;         0,78
user     ; LOBINDEX      ;       0,15;         0,00;         0,15
user     ; LOBSEGMENT    ;       3,48;         1,19;         4,67
user     ; TABLE         ;      12,11;         2,74;        14,85
address  ; INDEX         ;       0,12;         0,00;         0,12
(...)

Автор сценария:

DECLARE
  input_owner         NVARCHAR2(128) := 'MY_ORACLE_OWNER';
  segment_size_blocks NUMBER;
  segment_size_bytes  NUMBER;
  used_blocks         NUMBER;
  used_bytes          NUMBER;
  expired_blocks      NUMBER;
  expired_bytes       NUMBER;
  unexpired_blocks    NUMBER;
  unexpired_bytes     NUMBER;
  total_blocks        NUMBER;
  total_bytes         NUMBER;
  unused_blocks       NUMBER;
  unused_bytes        NUMBER;
  last_ext_file_id    NUMBER;
  last_ext_blk_id     NUMBER;
  last_used_blk       NUMBER;
  result_table        NVARCHAR2(128);
  result_segment_type NVARCHAR2(128);
  result_used_mb      NUMBER;
  result_unused_mb    NUMBER;
  result_total_mb     NUMBER;
  CURSOR cur
  IS
    SELECT
      s.segment_name   AS segment_name,
      s.owner          AS segment_owner,
      s.partition_name AS partition_name,
      s.segment_type   AS segment_type,
      CASE WHEN s.segment_type IN ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
        THEN s.segment_name
      WHEN s.segment_type IN ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
        THEN (SELECT i.table_name
              FROM dba_indexes i
              WHERE s.segment_name = i.index_name AND s.owner = i.owner)
      WHEN s.segment_type IN ('LOBSEGMENT', 'LOB PARTITION')
        THEN (SELECT l.table_name
              FROM dba_lobs l
              WHERE s.segment_name = l.segment_name AND s.owner = l.owner)
      WHEN s.segment_type IN ('LOBINDEX')
        THEN (SELECT l.table_name
              FROM dba_lobs l
              WHERE s.segment_name = l.index_name AND s.owner = l.owner)
      ELSE 'Unknown'
      END              AS table_name,
      s.bytes          AS segment_bytes
    FROM dba_segments s
    WHERE owner = input_owner
    ORDER BY table_name, segment_type;
BEGIN
  dbms_output.put_line('table                         ; segment type        ;   used (mb)     ; unused (mb)     ;  total (mb)');

  FOR ro IN cur
  LOOP

    result_table := ro.table_name;
    result_segment_type := ro.segment_type;

    IF ro.segment_type IN ('TABLE', 'INDEX')
    THEN
      dbms_space.unused_space(
          segment_owner             => ro.segment_owner,
          segment_name              => ro.segment_name,
          segment_type              => ro.segment_type,
          total_blocks              => total_blocks,
          total_bytes               => total_bytes,
          unused_blocks             => unused_blocks,
          unused_bytes              => unused_bytes,
          last_used_extent_file_id  => last_ext_file_id,
          last_used_extent_block_id => last_ext_blk_id,
          last_used_block           => last_used_blk);

      result_used_mb := (total_bytes - unused_bytes) / 1024 / 1024;
      result_unused_mb := unused_bytes / 1024 / 1024;
      result_total_mb := total_bytes / 1024 / 1024;

    ELSIF ro.segment_type IN ('LOBSEGMENT')
    THEN
      dbms_space.space_usage(
          segment_owner           => ro.segment_owner,
          segment_name            => ro.segment_name,
          segment_type            => 'LOB',
          partition_name          => ro.partition_name,
          segment_size_blocks     => segment_size_blocks,
          segment_size_bytes      => segment_size_bytes,
          used_blocks             => used_blocks,
          used_bytes              => used_bytes,
          expired_blocks          => expired_blocks,
          expired_bytes           => expired_bytes,
          unexpired_blocks        => unexpired_blocks,
          unexpired_bytes         => unexpired_bytes
      );
      result_used_mb := used_bytes / 1024 / 1024;
      result_unused_mb := (segment_size_bytes - used_bytes) / 1024 / 1024;
      result_total_mb := segment_size_bytes / 1024 / 1024;
    ELSE
      -- TODO ??
      result_used_mb := ro.segment_bytes / 1024 / 1024;
      result_unused_mb := 0;
      result_total_mb := result_used_mb + result_unused_mb;
    END IF;

    dbms_output.put_line(
        RPAD(result_table, 30) || '; ' ||
        RPAD(result_segment_type, 20)|| '; ' ||
        TO_CHAR(result_used_mb  / 1024 / 1024, '999999999990D00')|| '; ' ||
        TO_CHAR(result_unused_mb  / 1024 / 1024, '999999999990D00')|| '; ' ||
        TO_CHAR(result_total_mb / 1024 / 1024, '999999999990D00'));

  END LOOP;
END;
jeromerg
источник