Come trovare lo spazio effettivo consumato dagli indici su una tabella in Oracle?


11

Voglio trovare lo spazio effettivo consumato dagli indici su un tavolo in Oracle 10g. Non intendo includere lo spazio riservato da Oracle per un utilizzo futuro. (Il sovraccarico per Oracle non dovrebbe essere considerato.) Voglio i byte usati non i byte allocati.

Potete aiutarmi ad andare avanti?

Inoltre, esiste un modo per trovare le dimensioni effettive di un campo lungo in una tabella.

PS: vsize () e dbms_lob.getlength () non funzionano.


Puoi condividere perché quei due metodi non hanno funzionato per te?
jcolebrand

1
Dovresti porre la tua seconda domanda separatamente.
Leigh Riffel,

@Leigh buon punto. Vediamo se l'utente si rende conto di essere stato migrato e passa attraverso tutti i passaggi per ottenere risposta qui. Incrocio le dita per loro.
jcolebrand

Risposte:


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

ti mostrerà la quantità di spazio effettivamente consumata da ciascun indice. Non sono chiaro se questo è esattamente il tipo di overhead che stai cercando di spiegare e come stai distinguendo "usato" e "allocato" nel contesto di un indice. Se si desidera tenere conto dello spazio libero nell'indice, è possibile utilizzare la procedura DBMS_SPACE.SPACE_USAGE per determinare il numero di blocchi parzialmente vuoti nell'indice.


2
Credo che l'OP capisca come assegnato ciò che la tua query restituisce (e che non si restringe {automaticamente} dopo a delete <<name of table>>) rispetto alla dimensione utilizzata che varierebbe con il numero di voci nell'indice.
René Nyffenegger,

2
Questo comando è possibile senza accedere alle tabelle 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 - Supponendo che tu abbia effettuato l'accesso come utente Oracle che possiede l'indice, funzionerà. Se sei un DBA interessato a quanto spazio viene utilizzato, tuttavia, accederai generalmente come utente diverso da quello proprietario della tabella.
Grotta di Giustino,

6

Per misurare la (quella che credo sia la tua comprensione del) dimensione allocata e utilizzata dell'indice, probabilmente userei 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;
/

Questa procedura misura la dimensione allocata e utilizzata di un indice denominato * TQ84_SIZE_IX *. Per completezza, ho anche aggiunto il conteggio dei byte come riportato da user_segments.

Ora, questa procedura può essere vista in azione:

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;

Con una voce nell'indice, vengono restituite le seguenti cifre:

Space Used:      1078
Space Allocated: 65536
Segment:         65536

Riempimento dell'indice ...

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

... e ottenere di nuovo le cifre ...

exec tq84_index_size_proc;

...rapporti:

Space Used:      25579796
Space Allocated: 32505856
Segment:         32505856

Quindi, se l'indice viene "svuotato":

delete from tq84_size;
commit;
exec tq84_index_size_proc;

mostra:

Space Used:      4052714
Space Allocated: 32505856
Segment:         32505856

che dimostra che la dimensione allocata non si riduce mentre la dimensione utilizzata lo fa.


2

Nel caso in cui qualcuno venga qui alla ricerca di un modo per trovare le dimensioni di un campo lungo, di seguito è riportato un modo per farlo. Rimuoverò questa risposta se la domanda è separata.

Dati di esempio ...

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');

Funzione per fare il lavoro ... (Per la produzione questo dovrebbe essere in un pacchetto)

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;

Prova la funzione ...

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

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

0

Ho dovuto modificare la risposta di René Nyffenegger per rendere più generico e più semplice vedere l'utilizzo dello spazio per tutti gli indici in uno schema.

Ho pensato di condividere qui il codice modificato, nel caso in cui qualcun altro lo ritenga utile:

--==========================================
-- 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;
--==========================================
--==========================================
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.