Oracle의 테이블에서 인덱스가 소비하는 실제 공간을 찾는 방법은 무엇입니까?


11

oracle 10g의 테이블에서 인덱스가 소비하는 실제 공간을 찾고 싶습니다. 향후 사용을 위해 oracle이 예약 한 공간을 포함시키지 않습니다. (오라클에 의한 오버 헤드는 고려되지 않아야합니다.) 할당 된 바이트가 아닌 사용 된 바이트를 원합니다.

앞으로 나아갈 수 있습니까?

또한 테이블에서 긴 필드의 실제 크기를 찾는 방법이 있습니까?

PS : vsize () 및 dbms_lob.getlength ()가 작동하지 않습니다.


이 두 가지 방법이 효과가없는 이유를 공유 할 수 있습니까?
jcolebrand

1
두 번째 질문은 따로해야합니다.
레이 리펠

@ 좋은 지적. 사용자가 자신이 마이그레이션되었음을 알고 여기에서 답변을 받기 위해 모든 단계를 수행하는지 확인하십시오. 그들을 위해 내 손가락을 건너.
jcolebrand

stackoverflow.com/a/16661034/603516 도 참조하십시오 .
Vadzim

답변:


8
SELECT idx.index_name, SUM(bytes)
  FROM dba_segments seg,
       dba_indexes  idx
 WHERE idx.table_owner = <<owner of table>>
   AND idx.table_name  = <<name of table>>
   AND idx.owner       = seg.owner
   AND idx.index_name  = seg.segment_name
 GROUP BY idx.index_name

각 인덱스에서 실제로 소비 한 공간의 양을 보여줍니다. 그것이 정확히 어떤 종류의 오버 헤드를 설명하고 인덱스의 맥락에서 "사용"과 "할당"을 구별하고 있는지 확실하지 않습니다. 인덱스의 여유 공간을 고려하려는 경우 DBMS_SPACE.SPACE_USAGE 프로 시저 를 사용하여 인덱스에 부분적으로 비어있는 블록 수를 판별 할 수 있습니다 .


2
OP의 크기가 색인의 항목 수에 따라 달라지는 사용 된 크기 와 달리 쿼리가 반환하는 것 (및 {automatically} 줄어들지 않는)으로 할당 된 것으로 이해 합니다. delete <<name of table>>
René Nyffenegger

2
이 명령은 DBA 테이블에 액세스하지 않고도 가능합니다. SELECT idx.index_name, SUM(bytes) FROM user_segments seg, user_indexes idx WHERE idx.table_name = 'EMERGE_REPORTING_DETAIL' AND idx.index_name = seg.segment_name GROUP BY idx.index_name
Richard Dingwall

@RichardDingwall-인덱스를 소유 한 Oracle 사용자로 로그인했다고 가정하면 작동합니다. 그러나 사용중인 공간의 양에 관심이있는 DBA 인 경우 일반적으로 테이블을 소유 한 사용자 이외의 사용자로 로그인하게됩니다.
저스틴 동굴

6

인덱스의 할당 및 사용 크기 (내가 이해 한 것으로 생각하는 것)를 측정하려면 아마도 dbms_space

create or replace procedure tq84_index_size_proc 
as

  OBJECT_OWNER_in         varchar2(30) :=  user;
  OBJECT_NAME_in          varchar2(30) := 'TQ84_SIZE_IX';
  OBJECT_TYPE_in          varchar2(30) := 'INDEX';
  SAMPLE_CONTROL_in       number       :=  null;
  SPACE_USED_out          number;
  SPACE_ALLOCATED_out     number;
  CHAIN_PCENT_out         number;

  SUM_SEGMENT             number;

begin

  dbms_space.object_space_usage (
    OBJECT_OWNER           => OBJECT_OWNER_in        ,
    OBJECT_NAME            => OBJECT_NAME_in         ,
    OBJECT_TYPE            => OBJECT_TYPE_in         ,
    SAMPLE_CONTROL         => SAMPLE_CONTROL_in      ,
    SPACE_USED             => SPACE_USED_out         ,
    SPACE_ALLOCATED        => SPACE_ALLOCATED_out    ,
    CHAIN_PCENT            => CHAIN_PCENT_out
  );

  select sum(bytes) into SUM_SEGMENT 
    from user_segments
   where segment_name = OBJECT_NAME_in;


  dbms_output.put_line('Space Used:      ' || SPACE_USED_out);
  dbms_output.put_line('Space Allocated: ' || SPACE_ALLOCATED_out);
  dbms_output.put_line('Segment:         ' || SUM_SEGMENT);

end;
/

이 절차는 * TQ84_SIZE_IX *라는 색인의 할당 및 사용 크기를 측정합니다. 완벽을 기하기 위해 로보 고 된 바이트 수를 추가했습니다 user_segments.

이제이 절차를 실제로 볼 수 있습니다.

create table tq84_size (
  col_1 varchar2(40),
  col_2 number
);

create index tq84_size_ix on tq84_size(col_1);

insert into tq84_size values ('*', 0);
commit;
exec tq84_index_size_proc;

색인에 하나의 항목이 있으면 다음 그림이 리턴됩니다.

Space Used:      1078
Space Allocated: 65536
Segment:         65536

색인 작성 중 ...

insert into tq84_size 
select substr(object_name || object_type, 1, 40),
       rownum
  from dba_objects,
       dba_types
 where rownum < 500000;
commit;

... 그리고 다시 수치를 얻는 중 ...

exec tq84_index_size_proc;

... 보고서 :

Space Used:      25579796
Space Allocated: 32505856
Segment:         32505856

그런 다음 색인이 "비워진"경우 :

delete from tq84_size;
commit;
exec tq84_index_size_proc;

이것은 보여준다:

Space Used:      4052714
Space Allocated: 32505856
Segment:         32505856

이는 사용 된 크기는 줄이면서 할당 된 크기는 줄어들지 않음을 보여줍니다.


2

누군가가 긴 필드의 크기를 찾는 방법을 찾고 여기에 오는 경우 아래 방법이 있습니다. 질문이 분리되면이 답변을 제거 할 것입니다.

샘플 데이터 ...

CREATE TABLE TLONG 
(
  C1 Number(3),
  C2 LONG 
);

INSERT INTO TLONG VALUES (1,'abcd');
INSERT INTO TLONG VALUES (2,'abc');
INSERT INTO TLONG VALUES (3,'ab');
INSERT INTO TLONG VALUES (4,'1234567890');

작업을 수행하는 기능 ... (제작을 위해서는 패키지로 제공되어야 함)

CREATE OR REPLACE FUNCTION GetLongLength (pKey Number) RETURN Number Is
   vLong Long;
BEGIN
   SELECT C2 INTO vLong FROM TLONG WHERE C1 = pKey;
   Return Length(vLong);
END;
/

SHOW ERRORS;

기능 테스트 ...

SELECT rownum, GetLongLength(rownum) FROM dual CONNECT BY rownum<=4;

ROWNUM                 GETLONGLENGTH(ROWNUM)  
---------------------- ---------------------- 
1                      4                      
2                      3                      
3                      2                      
4                      10                   

0

René Nyffenegger의 답변을 수정하여 스키마의 모든 인덱스에 대한 공간 사용량을보다 일반적이고 쉽게 볼 수 있도록했습니다.

다른 사람이 유용하다고 생각하는 경우 수정 된 코드를 여기에서 공유한다고 생각했습니다.

--==========================================
-- Show space usage by all indexes in schema
--==========================================
-- Required to show output in SQLDeveloper, which would supress it otherwise.
SET SERVEROUTPUT ON;
-- Calculates size for given index
CREATE OR REPLACE PROCEDURE calc_index_size(
    index_name IN VARCHAR2)
AS
  OBJECT_OWNER_in     VARCHAR2(30) := USER;
  OBJECT_NAME_in      VARCHAR2(30) := index_name;
  OBJECT_TYPE_in      VARCHAR2(30) := 'INDEX';
  SAMPLE_CONTROL_in   NUMBER       := NULL;
  SPACE_USED_out      NUMBER;
  SPACE_ALLOCATED_out NUMBER;
  CHAIN_PCENT_out     NUMBER;
  SUM_SEGMENT         NUMBER;
BEGIN
  dbms_space.object_space_usage ( OBJECT_OWNER => OBJECT_OWNER_in , OBJECT_NAME => OBJECT_NAME_in , OBJECT_TYPE => OBJECT_TYPE_in , SAMPLE_CONTROL => SAMPLE_CONTROL_in , SPACE_USED => SPACE_USED_out , SPACE_ALLOCATED => SPACE_ALLOCATED_out , CHAIN_PCENT => CHAIN_PCENT_out );
  SELECT SUM(bytes)
  INTO SUM_SEGMENT
  FROM user_segments
  WHERE segment_name = OBJECT_NAME_in;
  dbms_output.put_line('Space Used:      ' || ROUND(SPACE_USED_out     /1024/1024, 2) || 'MB');
  dbms_output.put_line('Space Allocated: ' || ROUND(SPACE_ALLOCATED_out/1024/1024) || 'MB');
  dbms_output.put_line('Segment:         ' || ROUND(SUM_SEGMENT        /1024/1024) || 'MB');
END;
/
-- Shows index size for all indexes in a schema
DECLARE
BEGIN
  FOR user_indexes_sorted_by_size IN
  (SELECT idx.index_name,
    SUM(bytes)/1024/1024 AS "Size(MB)"
  FROM user_segments seg,
    user_indexes idx
  WHERE idx.index_name = seg.segment_name
  GROUP BY idx.index_name
  ORDER BY "Size(MB)" DESC
  )
  LOOP
    dbms_output.put_line( user_indexes_sorted_by_size.index_name );
    dbms_output.put_line( '-------------------------------------' );
    calc_index_size(user_indexes_sorted_by_size.index_name);
    dbms_output.put_line( '' );
  END LOOP;
END;
--==========================================
--==========================================
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.