Ich möchte den tatsächlichen Speicherplatz ermitteln, der von Indizes für eine Tabelle in Oracle 10g belegt wird. Ich beabsichtige nicht, den von Oracle für die zukünftige Verwendung reservierten Speicherplatz einzuschließen. (Der Overhead von Oracle sollte nicht berücksichtigt werden.) Ich möchte, dass die verwendeten Bytes nicht die zugewiesenen Bytes sind.
Können Sie mir dabei helfen?
Gibt es auch eine Möglichkeit, die tatsächliche Größe eines langen Felds in einer Tabelle zu ermitteln?.
PS: vsize () und dbms_lob.getlength () funktionieren nicht.
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
zeigt Ihnen den tatsächlich von jedem Index belegten Speicherplatz an. Mir ist nicht klar, ob Sie genau diese Art von Overhead berücksichtigen möchten und wie Sie im Kontext eines Index zwischen "verwendet" und "zugewiesen" unterscheiden. Wenn Sie freien Speicherplatz im Index berücksichtigen möchten, können Sie mit der Prozedur DBMS_SPACE.SPACE_USAGE bestimmen, wie viele teilweise leere Blöcke sich im Index befinden.
Um die zugewiesene und verwendete Größe des Index zu messen (ich glaube, Sie verstehen das), würde ich wahrscheinlich dbms_space
Verwenden.
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;
/
Diese Prozedur misst die zugewiesene und verwendete Größe eines Index mit dem Namen * TQ84_SIZE_IX *. Der Vollständigkeit halber habe ich auch die Anzahl der Bytes hinzugefügt, wie von user_segments
Angegeben.
Jetzt kann dieser Vorgang in Aktion gesehen werden:
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;
Mit einem Eintrag im Index werden folgende Zahlen zurückgegeben:
Space Used: 1078
Space Allocated: 65536
Segment: 65536
Index füllen ...
insert into tq84_size
select substr(object_name || object_type, 1, 40),
rownum
from dba_objects,
dba_types
where rownum < 500000;
commit;
... und die Zahlen wieder bekommen ...
exec tq84_index_size_proc;
... berichtet:
Space Used: 25579796
Space Allocated: 32505856
Segment: 32505856
Wenn der Index dann "geleert" wird:
delete from tq84_size;
commit;
exec tq84_index_size_proc;
es zeigt:
Space Used: 4052714
Space Allocated: 32505856
Segment: 32505856
dies zeigt, dass die zugewiesene Größe nicht kleiner wird als die verwendete Größe.
Falls jemand hierher kommt und nach einer Möglichkeit sucht, die Größe eines langen Feldes zu ermitteln, finden Sie unten eine Möglichkeit, dies zu tun. Ich werde diese Antwort entfernen, wenn die Frage getrennt ist.
Beispieldaten...
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');
Funktion, um die Arbeit zu erledigen ... (Für die Produktion sollte dies in einem Paket sein)
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;
Testen Sie die Funktion ...
SELECT rownum, GetLongLength(rownum) FROM dual CONNECT BY rownum<=4;
ROWNUM GETLONGLENGTH(ROWNUM)
---------------------- ----------------------
1 4
2 3
3 2
4 10
Ich musste die Antwort von René Nyffenegger ändern, um die Speicherplatznutzung für alle Indizes in einem Schema allgemeiner und einfacher zu gestalten.
Ich dachte, ich würde den geänderten Code hier teilen, falls jemand anderes ihn nützlich findet:
--==========================================
-- 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;
--==========================================
--==========================================