오라클 : 테이블이 사용하는 스토리지 공간을 찾는 방법은 무엇입니까?


답변:


17

OEM 10g를 통해,

  1. 평소와 같이 데이터베이스에 연결
  2. Schema탭을 클릭 하십시오
  3. Tables데이터베이스 개체 내에서 링크
  4. 스키마 이름과 객체 이름을 입력하고 (선택 사항) Go
  5. 라디오 버튼을 사용하여 보려는 테이블을 선택하고 클릭하십시오 Edit (테이블 이름 링크를 클릭하지 마십시오)
  6. Segments탭을 클릭 하십시오 (그리고 기다리십시오 ...)
  7. 테이블 데이터의 크기와 사용 된 인덱스가 표시됩니다.

자, 그것은 기술적으로 귀하의 질문에 대답했습니다. 그러나 더 좋은 방법은 다음과 같습니다.

  1. SQLPLUS를 사용하여 로그온
  2. Vincent에서 스크립트를 실행하십시오.

스크립트를 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

인덱스를 고려하지 않기 때문에 이것이 작동하는지 확실하지 않습니까?
Codek

1
@ 코덱 : 맞습니다. 이것은 테이블 자체에서 사용하는 공간입니다. 그러나 인덱스가 세그먼트이고 범위가 있기 때문에 동일한 방법으로 인덱스가 사용하는 공간을 계산할 수 있습니다.
Vincent

실제로-인덱스의 "이름"이 무엇이든 될 수 있다는 점에서 까다로울 수 있습니다!
Codek

1
LOB 열이없는 테이블에서만 작동합니다.
pacoverflow

@pacoverflow 좋은 지적 !
Vincent

8

all_tables보기를 사용한 원래 접근 방식에 LOB 범위가 포함되어 있습니까? 나는 생각하지 않을 것입니다. 내가 찾은 것은 다음과 같습니다.

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 검색 및 실험 후 가장 정확한 결과를 제공하는 다음 쿼리를 작성했습니다. Oracle 사용자의 경우 테이블 및 세그먼트 유형 (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;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.