Oracleでテーブルサイズを計算する方法


128

MSSQLに慣れているため(そして潜在的に台無しになっている)、Oracle 10gでテーブルサイズを取得する方法を知りたいと思います。私はそれをグーグルで調べたので、sp_spaceusedほど簡単なオプションがないかもしれないことに気づきました。それでも、私が得た潜在的な答えはほとんどの場合時代遅れであるか、機能しません。おそらく、私が作業しているスキーマのDBAではないためです。

誰かが解決策や推奨事項を持っていますか?


プロシージャに答えを与えるのが台無しになっている場合は、ここから得た答えを受け取ってプロシージャにラップし、それを呼び出します... dun dun duh ... sp_spaceused。魔法はほとんどありません。

1
@MarkBradyたぶん魔法ではなくトン難解な知識のが必要です。
jpmc26 2016年

回答:


201

このクエリに興味があるかもしれません。これは、インデックスとテーブル上のLOBを考慮して、各テーブルに割り当てられているスペースの量を示します。多くの場合、テーブル自体だけでなく、「インデックスを含め、注文書テーブルが占めるスペースの量」を知りたいと思っています。いつでも詳細を掘り下げることができます。これにはDBA_ *ビューへのアクセスが必要であることに注意してください。

COLUMN TABLE_NAME FORMAT A32
COLUMN OBJECT_NAME FORMAT A32
COLUMN OWNER FORMAT A10

SELECT
   owner, 
   table_name, 
   TRUNC(sum(bytes)/1024/1024) Meg,
   ROUND( ratio_to_report( sum(bytes) ) over () * 100) Percent
FROM
(SELECT segment_name table_name, owner, bytes
 FROM dba_segments
 WHERE segment_type IN ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
 UNION ALL
 SELECT i.table_name, i.owner, s.bytes
 FROM dba_indexes i, dba_segments s
 WHERE s.segment_name = i.index_name
 AND   s.owner = i.owner
 AND   s.segment_type IN ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
 UNION ALL
 SELECT l.table_name, l.owner, s.bytes
 FROM dba_lobs l, dba_segments s
 WHERE s.segment_name = l.segment_name
 AND   s.owner = l.owner
 AND   s.segment_type IN ('LOBSEGMENT', 'LOB PARTITION')
 UNION ALL
 SELECT l.table_name, l.owner, s.bytes
 FROM dba_lobs l, dba_segments s
 WHERE s.segment_name = l.index_name
 AND   s.owner = l.owner
 AND   s.segment_type = 'LOBINDEX')
WHERE owner in UPPER('&owner')
GROUP BY table_name, owner
HAVING SUM(bytes)/1024/1024 > 10  /* Ignore really small tables */
ORDER BY SUM(bytes) desc
;

1
この回答はセグメントをカウントすることに注意してください。セグメントは現在使用中のスペースと以前に使用されていたスペースを区別しません。明らかに、セグメントがテーブルに割り当てられると、スペースが解放されていても、常にセグメントがテーブルに割り当てられます。こちらをご覧ください。実際に使用されているスペースの量を確認するには、エクステントレベルまで下げる必要があると思います。
jpmc26 2016年

43
-- Tables + Size MB
select owner, table_name, round((num_rows*avg_row_len)/(1024*1024)) MB 
from all_tables 
where owner not like 'SYS%'  -- Exclude system tables.
and num_rows > 0  -- Ignore empty Tables.
order by MB desc -- Biggest first.
;


--Tables + Rows
select owner, table_name, num_rows
 from all_tables 
where owner not like 'SYS%'  -- Exclude system tables.
and num_rows > 0  -- Ignore empty Tables.
order by num_rows desc -- Biggest first.
;

注:これらは推定値であり、収集統計でより正確になります。

exec dbms_utility.analyze_schema(user,'COMPUTE');

2
これらの統計はnullnum_rowsavg_row_len)の場合があります。次のステートメントを使用する前に分析を行う必要がありますANALYZE TABLE your_table COMPUTE STATISTICS
Brice

これらの分析は非常に時間がかかる場合があります。
Brice、

非テーブルスペーステーブルをチェックできない場合の
回避策

30

まず、一般に、スペース分析を行うためにテーブル統計を収集することは潜在的に危険なことであると警告します。統計の収集はクエリプランを変更する可能性があります。特に、DBAが呼び出しが使用していないデフォルト以外のパラメーターを使用する統計収集ジョブを構成している場合、Oracleは問題のあるテーブルを利用するクエリを再解析します。ヒット。DBAが意図的に一部のテーブルを統計なしで残した場合(一般的にOPTIMIZER_MODECHOOSEの場合)、統計を収集すると、Oracleがルールベースのオプティマイザーの使用を停止し、一連のクエリに対してコストベースのオプティマイザーの使用を開始する可能性があります。生産で予期せず行われた場合の頭痛。統計が正確であれば、クエリを実行できますUSER_TABLESALL_TABLESまたはDBA_TABLESを呼び出さずに直接)GATHER_TABLE_STATS。統計が正確でない場合は、おそらくその理由があり、現状を乱したくないでしょう。

次に、SQL Serverのsp_spaceused手順に最も近いものは、おそらくOracleのDBMS_SPACEパッケージです。トム・カイトには、このパッケージへのシンプルなインターフェースを提供し、出力されるものと同様の情報を出力する素晴らしいshow_space手順がありますsp_spaceused


8

まず、テーブルのオプティマイザ統計を収集します(まだの場合)。

begin
   dbms_stats.gather_table_stats('MYSCHEMA','MYTABLE');
end;
/

警告:ジャスティンが彼の回答で述べているように、オプティマイザ統計の収集はクエリの最適化に影響を与えるため、十分な注意と考慮なしに行うべきではありません

次に、生成された統計から、テーブルが占めるブロックの数を見つけます。

select blocks, empty_blocks, num_freelist_blocks
from   all_tables
where  owner = 'MYSCHEMA'
and    table_name = 'MYTABLE';
  • テーブルに割り当てられたブロックの総数は、blocks + empty_blocks + num_freelist_blocksです。

  • blocksは、実際にデータを含むブロックの数です。

ブロック数に使用中のブロックサイズ(通常は8KB)を掛けて、消費されたスペースを取得します-たとえば、17ブロックx 8KB = 136KB。

これをスキーマ内のすべてのテーブルに対して一度に行うには:

begin
    dbms_stats.gather_schema_stats ('MYSCHEMA');
end;
/

select table_name, blocks, empty_blocks, num_freelist_blocks
from   user_tables;

注:このAskTomスレッドを読んだ後に上記に加えられた変更


7

WWのクエリを変更して、より詳細な情報を提供します。

SELECT * FROM (
  SELECT
    owner, object_name, object_type, table_name, ROUND(bytes)/1024/1024 AS meg,
    tablespace_name, extents, initial_extent,
    ROUND(Sum(bytes/1024/1024) OVER (PARTITION BY table_name)) AS total_table_meg
  FROM (
    -- Tables
    SELECT owner, segment_name AS object_name, 'TABLE' AS object_type,
          segment_name AS table_name, bytes,
          tablespace_name, extents, initial_extent
    FROM   dba_segments
    WHERE  segment_type IN ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
    UNION ALL
    -- Indexes
    SELECT i.owner, i.index_name AS object_name, 'INDEX' AS object_type,
          i.table_name, s.bytes,
          s.tablespace_name, s.extents, s.initial_extent
    FROM   dba_indexes i, dba_segments s
    WHERE  s.segment_name = i.index_name
    AND    s.owner = i.owner
    AND    s.segment_type IN ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
    -- LOB Segments
    UNION ALL
    SELECT l.owner, l.column_name AS object_name, 'LOB_COLUMN' AS object_type,
          l.table_name, s.bytes,
          s.tablespace_name, s.extents, s.initial_extent
    FROM   dba_lobs l, dba_segments s
    WHERE  s.segment_name = l.segment_name
    AND    s.owner = l.owner
    AND    s.segment_type = 'LOBSEGMENT'
    -- LOB Indexes
    UNION ALL
    SELECT l.owner, l.column_name AS object_name, 'LOB_INDEX' AS object_type,
          l.table_name, s.bytes,
          s.tablespace_name, s.extents, s.initial_extent
    FROM   dba_lobs l, dba_segments s
    WHERE  s.segment_name = l.index_name
    AND    s.owner = l.owner
    AND    s.segment_type = 'LOBINDEX'
  )
  WHERE owner = UPPER('&owner')
)
WHERE total_table_meg > 10
ORDER BY total_table_meg DESC, meg DESC
/

6

サブパーティションテーブルとインデックスの場合、次のクエリを使用できます



    SELECT owner, table_name, ROUND(sum(bytes)/1024/1024/1024, 2) GB
    FROM
    (SELECT segment_name table_name, owner, bytes
     FROM dba_segments
     WHERE segment_type IN ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
     UNION ALL
     SELECT i.table_name, i.owner, s.bytes
     FROM dba_indexes i, dba_segments s
     WHERE s.segment_name = i.index_name
     AND   s.owner = i.owner
     AND   s.segment_type IN ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
     UNION ALL
     SELECT l.table_name, l.owner, s.bytes
     FROM dba_lobs l, dba_segments s
     WHERE s.segment_name = l.segment_name
     AND   s.owner = l.owner
     AND   s.segment_type = 'LOBSEGMENT'
     UNION ALL
     SELECT l.table_name, l.owner, s.bytes
     FROM dba_lobs l, dba_segments s
     WHERE s.segment_name = l.index_name
     AND   s.owner = l.owner
     AND   s.segment_type = 'LOBINDEX')
    WHERE owner in UPPER('&owner')
    GROUP BY table_name, owner
    HAVING SUM(bytes)/1024/1024 > 10  /* Ignore really small tables */
    ORDER BY SUM(bytes) DESC
    ;

5

IIRC必要なテーブルは、DBA_TABLES、DBA_EXTENTSまたはDBA_SEGMENTSおよびDBA_DATA_FILESです。マシンの管理権限がない場合に確認できるテーブルには、これらのバージョンのUSER_バージョンとALL_バージョンもあります。


4

WWsの回答のバリエーションを示します。上記の他のセクションで提案されているように、パーティションとサブパーティションが含まれ、さらにTYPEを示す列が含まれます:テーブル/インデックス/ LOBなど

SELECT
   owner, "Type", table_name "Name", TRUNC(sum(bytes)/1024/1024) Meg
FROM
(  SELECT segment_name table_name, owner, bytes, 'Table' as "Type"
   FROM dba_segments
   WHERE segment_type in  ('TABLE','TABLE PARTITION','TABLE SUBPARTITION')
 UNION ALL
   SELECT i.table_name, i.owner, s.bytes, 'Index' as "Type"
   FROM dba_indexes i, dba_segments s
   WHERE s.segment_name = i.index_name
   AND   s.owner = i.owner
   AND   s.segment_type in ('INDEX','INDEX PARTITION','INDEX SUBPARTITION')
 UNION ALL
   SELECT l.table_name, l.owner, s.bytes, 'LOB' as "Type"
   FROM dba_lobs l, dba_segments s
   WHERE s.segment_name = l.segment_name
   AND   s.owner = l.owner
   AND   s.segment_type IN ('LOBSEGMENT','LOB PARTITION','LOB SUBPARTITION')
 UNION ALL
   SELECT l.table_name, l.owner, s.bytes, 'LOB Index' as "Type"
   FROM dba_lobs l, dba_segments s
   WHERE s.segment_name = l.index_name
   AND   s.owner = l.owner
   AND   s.segment_type = 'LOBINDEX')
   WHERE owner in UPPER('&owner')
GROUP BY table_name, owner, "Type"
HAVING SUM(bytes)/1024/1024 > 10  /* Ignore really small tables */
ORDER BY SUM(bytes) desc;

3
select segment_name,segment_type,bytes/1024/1024 MB
from dba_segments
where segment_name='TABLENAME' and owner ='OWNERNAME' order by mb desc;

2

テーブルスペースごとのスキーマサイズを取得するようにクエリを変更しました。

SELECT owner,
     tablespace_name,
     TRUNC (SUM (bytes) / 1024 / 1024)   Meg,
     ROUND (ratio_to_report (SUM (bytes)) OVER () * 100) Percent
FROM (SELECT tablespace_name, owner, bytes
        FROM dba_segments
       WHERE segment_type IN
                 ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
      UNION ALL
      SELECT i.tablespace_name, i.owner, s.bytes
        FROM dba_indexes i, dba_segments s
       WHERE     s.segment_name = i.index_name
             AND s.owner = i.owner
             AND s.segment_type IN
                     ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
      UNION ALL
      SELECT l.tablespace_name, l.owner, s.bytes
        FROM dba_lobs l, dba_segments s
       WHERE     s.segment_name = l.segment_name
             AND s.owner = l.owner
             AND s.segment_type IN ('LOBSEGMENT', 'LOB PARTITION')
      UNION ALL
      SELECT l.tablespace_name, l.owner, s.bytes
        FROM dba_lobs l, dba_segments s
       WHERE     s.segment_name = l.index_name
             AND s.owner = l.owner
             AND s.segment_type = 'LOBINDEX')
WHERE owner IN UPPER ('&owner')
GROUP BY owner, tablespace_name
--HAVING SUM(bytes)/1024/1024 > 10  /* Ignore really small tables */
ORDER BY tablespace_name -- desc
;

1

「テーブルのサイズ」の意味によって異なります。テーブルは、ファイルシステム上の特定のファイルとは関係ありません。テーブルはテーブルスペースに常駐します(パーティション化されている場合は複数のテーブルスペース、そしてテーブルのインデックスも考慮したい場合は複数のテーブルスペース)。多くの場合、テーブルスペースには複数のテーブルがあり、複数のファイルに分散している場合があります。

テーブルの将来の成長に必要なスペースの量を見積もる場合は、avg_row_lenにテーブルの行数(またはテーブルに期待する行数)を掛けた値が適切なガイドになります。ただし、Oracleは各ブロックに空き領域を残し、一部は更新された行を「拡張」できるようにします。一部はそのブロックに別の行全体を収めることができないためです(たとえば、8Kブロックは2行しか収められません) 3Kは、3Kがほとんどの行サイズよりもはるかに大きいため、極端な例です。したがって、BLOCKS(USER_TABLES内)がより良いガイドになる可能性があります。

しかし、テーブルに200,000行があり、それらの半分を削除した場合、テーブルは同じ数のブロックを「所有」します。他のテーブルで使用するために解放されません。また、ブロックはテーブルに個別に追加されるのではなく、「エクステント」と呼ばれるグループで追加されます。そのため、通常はテーブルにEMPTY_BLOCKS(これもUSER_TABLESにあります)があります。


1

分割テーブルの修正:

SELECT owner, table_name, ROUND(sum(bytes)/1024/1024/1024, 2) GB
FROM
(SELECT segment_name table_name, owner, bytes
 FROM dba_segments
 WHERE segment_type IN ('TABLE', 'TABLE PARTITION', 'TABLE SUBPARTITION')
 UNION ALL
 SELECT i.table_name, i.owner, s.bytes
 FROM dba_indexes i, dba_segments s
 WHERE s.segment_name = i.index_name
 AND   s.owner = i.owner
 AND   s.segment_type IN ('INDEX', 'INDEX PARTITION', 'INDEX SUBPARTITION')
 UNION ALL
 SELECT l.table_name, l.owner, s.bytes
 FROM dba_lobs l, dba_segments s
 WHERE s.segment_name = l.segment_name
 and   s.owner = l.owner
 AND   s.segment_type in ('LOBSEGMENT', 'LOB PARTITION', 'LOB SUBPARTITION')
 UNION ALL
 SELECT l.table_name, l.owner, s.bytes
 FROM dba_lobs l, dba_segments s
 WHERE s.segment_name = l.index_name
 AND   s.owner = l.owner
 AND   s.segment_type = 'LOBINDEX')
WHERE owner in UPPER('&owner')
GROUP BY table_name, owner
HAVING SUM(bytes)/1024/1024 > 10  /* Ignore really small tables */
order by sum(bytes) desc
;

0

ブロックサイズに基づいてテーブルの未加工サイズを返す単純な選択には、インデックス付きのサイズも含まれます

select table_name、(nvl((select sum(blocks)from dba_indexes a、dba_segments b where a.index_name = b.segment_name and a.table_name = dba_tables.table_name)、0)+ blocks)* 8192/1024 TotalSize、blocks * 8 dba_tablesのtableSizeは3で並べます


0

これはもう少し正確であることがわかりました:

SELECT
   owner, table_name, TRUNC(sum(bytes)/1024/1024/1024) GB
FROM
(SELECT segment_name table_name, owner, bytes
FROM dba_segments
WHERE segment_type in  ('TABLE','TABLE PARTITION')
UNION ALL
SELECT i.table_name, i.owner, s.bytes
FROM dba_indexes i, dba_segments s
WHERE s.segment_name = i.index_name
AND   s.owner = i.owner
AND   s.segment_type in ('INDEX','INDEX PARTITION')
UNION ALL
SELECT l.table_name, l.owner, s.bytes
FROM dba_lobs l, dba_segments s
WHERE s.segment_name = l.segment_name
AND   s.owner = l.owner
AND   s.segment_type IN ('LOBSEGMENT','LOB PARTITION')
UNION ALL
SELECT l.table_name, l.owner, s.bytes
FROM dba_lobs l, dba_segments s
WHERE s.segment_name = l.index_name
AND   s.owner = l.owner
AND   s.segment_type = 'LOBINDEX')
---WHERE owner in UPPER('&owner')
GROUP BY table_name, owner
HAVING SUM(bytes)/1024/1024 > 10  /* Ignore really small tables */
ORDER BY SUM(bytes) desc

7
私の答えのように見えますか?
WW。

0
select segment_name as tablename, sum(bytes/ (1024 * 1024 * 1024)) as tablesize_in_GB
From dba_segments /* if looking at tables not owned by you else use user_segments */
where segment_name = 'TABLE_WHOSE_SIZE_I_WANT_TO_KNOW'
and   OWNER = 'WHO OWNS THAT TABLE' /* if user_segments is used delete this line */ 
group by segment_name ;

-2

結合で「選択」サイズを取得できるもう1つのオプションと、オプションとしてのテーブルサイズ

-- 1
EXPLAIN PLAN
   FOR
      SELECT
            Scheme.Table_name.table_column1 AS "column1",
            Scheme.Table_name.table_column2 AS "column2",
            Scheme.Table_name.table_column3 AS "column3",
            FROM Scheme.Table_name
       WHERE ;

SELECT * FROM TABLE (DBMS_XPLAN.display);

-3

テーブルデータ、テーブルインデックス、BLOBフィールドのセグメントを計算する最後のものと同じバリアントがあります。

CREATE OR REPLACE FUNCTION
  SYS.RAZMER_TABLICY_RAW(pNazvanie in varchar, pOwner in varchar2)
return number
is
  val number(16);
  sz number(16);
begin
  sz := 0;

  --Calculate size of table data segments
  select
    sum(t.bytes) into val
  from
    sys.dba_segments t
  where
    t.segment_name = upper(pNazvanie)
  and
    t.owner = upper(pOwner);
  sz := sz + nvl(val,0);

  --Calculate size of table indexes segments
  select
    sum(s.bytes) into val
  from
    all_indexes t
  inner join
    dba_segments s
  on
    t.index_name = s.segment_name
  where
    t.table_name = upper(pNazvanie)
  and
    t.owner = upper(pOwner);
  sz := sz + nvl(val,0);

  --Calculate size of table blob segments
  select
    sum(s.bytes) into val
  from
    all_lobs t
  inner join
    dba_segments s on t.segment_name = s.segment_name
  where
    t.table_name = upper(pNazvanie)
  and
    t.owner = upper(pOwner);
  sz := sz + nvl(val,0);

  return sz;

end razmer_tablicy_raw;

ソース

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.