Bagaimana menemukan ruang aktual yang dikonsumsi oleh indeks di atas meja di Oracle?

11

Saya ingin menemukan ruang aktual yang dikonsumsi oleh indeks di atas meja di oracle 10g. Saya tidak bermaksud memasukkan ruang yang disediakan oleh oracle untuk penggunaan di masa mendatang. (Overhead oleh oracle seharusnya tidak dipertimbangkan.) Saya ingin byte yang digunakan bukan byte yang dialokasikan.

Bisakah Anda membantu saya untuk maju?

Juga, apakah ada cara untuk menemukan ukuran sebenarnya dari bidang panjang dalam sebuah tabel.

PS: vsize () dan dbms_lob.getlength () tidak berfungsi.

Egaliter
sumber
Bisakah Anda berbagi mengapa kedua metode itu tidak berhasil untuk Anda?
jcolebrand
1
Anda harus mengajukan pertanyaan kedua secara terpisah.
Leigh Riffel
@ Poin bagus. Mari kita lihat apakah pengguna menyadari bahwa mereka telah dimigrasi dan menjalani semua langkah untuk dijawab di sini. Menyilangkan jari saya atas nama mereka.
jcolebrand

Jawaban:

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

akan menunjukkan jumlah ruang yang benar-benar dikonsumsi oleh setiap indeks. Saya tidak jelas apakah itu jenis overhead yang Anda coba pertanggungjawabkan dan bagaimana Anda membedakan "bekas" dan "dialokasikan" dalam konteks indeks. Jika Anda ingin memperhitungkan ruang kosong dalam indeks, Anda dapat menggunakan prosedur DBMS_SPACE.SPACE_USAGE untuk menentukan berapa banyak blok kosong sebagian dalam indeks.

Gua Justin
sumber
2
Saya percaya OP memahami bahwa alokasi adalah apa yang dikembalikan oleh kueri Anda (dan itu tidak {secara otomatis} menyusut setelah a delete <<name of table>>) dibandingkan dengan ukuran yang digunakan yang akan bervariasi dengan jumlah entri dalam indeks.
René Nyffenegger
2
Perintah ini dimungkinkan tanpa mengakses tabel 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 - Dengan anggapan bahwa Anda masuk sebagai pengguna Oracle yang memiliki indeks, itu akan berfungsi. Namun, jika Anda seorang DBA yang tertarik pada seberapa banyak ruang yang digunakan, Anda umumnya akan masuk sebagai pengguna selain dari yang memiliki tabel.
Justin Cave
6

Untuk mengukur (apa yang saya percaya adalah pengertian Anda tentang) ukuran indeks yang dialokasikan dan digunakan, saya mungkin akan menggunakan 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;
/

Prosedur ini mengukur ukuran indeks yang dialokasikan dan digunakan bernama * TQ84_SIZE_IX *. Demi kelengkapan, saya juga menambahkan hitungan byte seperti yang dilaporkan oleh user_segments.

Sekarang, prosedur ini dapat dilihat dalam tindakan:

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;

Dengan satu entri dalam indeks, angka-angka berikut dikembalikan:

Space Used:      1078
Space Allocated: 65536
Segment:         65536

Mengisi indeks ...

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

... dan mendapatkan angka lagi ...

exec tq84_index_size_proc;

... laporan:

Space Used:      25579796
Space Allocated: 32505856
Segment:         32505856

Kemudian, jika indeks "dikosongkan":

delete from tq84_size;
commit;
exec tq84_index_size_proc;

itu menunjukkan:

Space Used:      4052714
Space Allocated: 32505856
Segment:         32505856

yang menunjukkan bahwa ukuran yang dialokasikan tidak menyusut sedangkan ukuran yang digunakan tidak.

René Nyffenegger
sumber
2

Jika seseorang datang ke sini mencari cara untuk menemukan ukuran bidang yang panjang, di bawah ini adalah cara untuk melakukannya. Saya akan menghapus jawaban ini jika pertanyaannya dipisahkan.

Contoh data...

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

Berfungsi untuk melakukan pekerjaan ... (Untuk produksi ini harus dalam satu paket)

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;

Uji fungsinya ...

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

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

Saya harus mengubah jawaban René Nyffenegger untuk membuatnya lebih umum dan lebih mudah untuk melihat penggunaan ruang untuk semua indeks dalam suatu skema.

Saya pikir saya akan membagikan kode yang dimodifikasi di sini, kalau-kalau ada orang yang merasa berguna:

--==========================================
-- 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
sumber