¿Cómo encontrar el espacio real que consumen los índices en una tabla en Oracle?

11

Quiero encontrar el espacio real que consumen los índices en una tabla en Oracle 10g. No tengo la intención de incluir el espacio reservado por Oracle para uso futuro. (No se debe considerar la sobrecarga por Oracle). Quiero los bytes usados, no los bytes asignados.

¿Me pueden ayudar a seguir adelante?

Además, ¿hay alguna manera de encontrar el tamaño real de un campo largo en una tabla?

PD: vsize () y dbms_lob.getlength () no funcionan.

Igualitario
fuente
¿Puedes compartir por qué esos dos métodos no funcionaron para ti?
jcolebrand
1
Debe hacer su segunda pregunta por separado.
Leigh Riffel
@Leigh buen punto. Veamos si el usuario se da cuenta de que ha sido migrado y sigue todos los pasos para obtener una respuesta aquí. Cruzando los dedos en su nombre.
jcolebrand
Consulte también stackoverflow.com/a/16661034/603516 .
Vadzim

Respuestas:

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

le mostrará la cantidad de espacio realmente consumido por cada índice. No estoy claro si eso es exactamente qué tipo de sobrecarga está tratando de explicar y cómo distingue "usado" y "asignado" en el contexto de un índice. Si desea tener en cuenta el espacio libre en el índice, puede usar el procedimiento DBMS_SPACE.SPACE_USAGE para determinar cuántos bloques parcialmente vacíos hay en el índice.

Justin Cave
fuente
2
Creo que el OP entiende que lo asignado es lo que devuelve su consulta (y que no se reduce {automáticamente} después de a delete <<name of table>>) en comparación con el tamaño utilizado que variaría con el número de entradas en el índice.
René Nyffenegger
2
Este comando es posible sin acceder a las tablas de 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: suponiendo que haya iniciado sesión como el usuario de Oracle que posee el índice, funcionará. Sin embargo, si usted es un DBA interesado en la cantidad de espacio que se está utilizando, generalmente iniciará sesión como un usuario que no sea el propietario de la tabla.
Justin Cave
6

Para medir el tamaño del índice (lo que creo que es su comprensión del) asignado y usado, probablemente usaría 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;
/

Este procedimiento mide el tamaño asignado y utilizado de un índice llamado * TQ84_SIZE_IX *. Para completar, también he agregado el recuento de bytes según lo informado por user_segments.

Ahora, este procedimiento se puede ver en acción:

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 entrada en el índice, se devuelven las siguientes cifras:

Space Used:      1078
Space Allocated: 65536
Segment:         65536

Llenar el índice ...

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

... y obteniendo las cifras otra vez ...

exec tq84_index_size_proc;

...informes:

Space Used:      25579796
Space Allocated: 32505856
Segment:         32505856

Entonces, si el índice está "vacío":

delete from tq84_size;
commit;
exec tq84_index_size_proc;

muestra:

Space Used:      4052714
Space Allocated: 32505856
Segment:         32505856

lo que demuestra que el tamaño asignado no se reduce mientras que el tamaño utilizado sí.

René Nyffenegger
fuente
2

En caso de que alguien venga buscando una forma de encontrar el tamaño de un campo largo, a continuación hay una forma de hacerlo. Eliminaré esta respuesta si la pregunta está separada.

Data de muestra...

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

Función para hacer el trabajo ... (Para producción, esto debería estar en un paquete)

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;

Probar la función ...

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

ROWNUM                 GETLONGLENGTH(ROWNUM)  
---------------------- ---------------------- 
1                      4                      
2                      3                      
3                      2                      
4                      10                   
Leigh Riffel
fuente
0

Tuve que modificar la respuesta de René Nyffenegger para que sea más genérico y más fácil ver el uso del espacio para todos los índices en un esquema.

Pensé que compartiría el código modificado aquí, en caso de que alguien más lo encuentre útil:

--==========================================
-- 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;
--==========================================
--==========================================
Kshitiz Sharma
fuente