MSSQLに慣れているため(そして潜在的に台無しになっている)、Oracle 10gでテーブルサイズを取得する方法を知りたいと思います。私はそれをグーグルで調べたので、sp_spaceusedほど簡単なオプションがないかもしれないことに気づきました。それでも、私が得た潜在的な答えはほとんどの場合時代遅れであるか、機能しません。おそらく、私が作業しているスキーマのDBAではないためです。
誰かが解決策や推奨事項を持っていますか?
MSSQLに慣れているため(そして潜在的に台無しになっている)、Oracle 10gでテーブルサイズを取得する方法を知りたいと思います。私はそれをグーグルで調べたので、sp_spaceusedほど簡単なオプションがないかもしれないことに気づきました。それでも、私が得た潜在的な答えはほとんどの場合時代遅れであるか、機能しません。おそらく、私が作業しているスキーマのDBAではないためです。
誰かが解決策や推奨事項を持っていますか?
回答:
このクエリに興味があるかもしれません。これは、インデックスとテーブル上の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
;
-- 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');
null
(num_rows
、avg_row_len
)の場合があります。次のステートメントを使用する前に分析を行う必要がありますANALYZE TABLE your_table COMPUTE STATISTICS
まず、一般に、スペース分析を行うためにテーブル統計を収集することは潜在的に危険なことであると警告します。統計の収集はクエリプランを変更する可能性があります。特に、DBAが呼び出しが使用していないデフォルト以外のパラメーターを使用する統計収集ジョブを構成している場合、Oracleは問題のあるテーブルを利用するクエリを再解析します。ヒット。DBAが意図的に一部のテーブルを統計なしで残した場合(一般的にOPTIMIZER_MODE
CHOOSEの場合)、統計を収集すると、Oracleがルールベースのオプティマイザーの使用を停止し、一連のクエリに対してコストベースのオプティマイザーの使用を開始する可能性があります。生産で予期せず行われた場合の頭痛。統計が正確であれば、クエリを実行できますUSER_TABLES
(ALL_TABLES
またはDBA_TABLES
を呼び出さずに直接)GATHER_TABLE_STATS
。統計が正確でない場合は、おそらくその理由があり、現状を乱したくないでしょう。
次に、SQL Serverのsp_spaceused
手順に最も近いものは、おそらくOracleのDBMS_SPACE
パッケージです。トム・カイトには、このパッケージへのシンプルなインターフェースを提供し、出力されるものと同様の情報を出力する素晴らしいshow_space
手順がありますsp_spaceused
。
まず、テーブルのオプティマイザ統計を収集します(まだの場合)。
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スレッドを読んだ後に上記に加えられた変更
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
/
サブパーティションテーブルとインデックスの場合、次のクエリを使用できます
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
;
IIRC必要なテーブルは、DBA_TABLES、DBA_EXTENTSまたはDBA_SEGMENTSおよびDBA_DATA_FILESです。マシンの管理権限がない場合に確認できるテーブルには、これらのバージョンのUSER_バージョンとALL_バージョンもあります。
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;
テーブルスペースごとのスキーマサイズを取得するようにクエリを変更しました。
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
;
「テーブルのサイズ」の意味によって異なります。テーブルは、ファイルシステム上の特定のファイルとは関係ありません。テーブルはテーブルスペースに常駐します(パーティション化されている場合は複数のテーブルスペース、そしてテーブルのインデックスも考慮したい場合は複数のテーブルスペース)。多くの場合、テーブルスペースには複数のテーブルがあり、複数のファイルに分散している場合があります。
テーブルの将来の成長に必要なスペースの量を見積もる場合は、avg_row_lenにテーブルの行数(またはテーブルに期待する行数)を掛けた値が適切なガイドになります。ただし、Oracleは各ブロックに空き領域を残し、一部は更新された行を「拡張」できるようにします。一部はそのブロックに別の行全体を収めることができないためです(たとえば、8Kブロックは2行しか収められません) 3Kは、3Kがほとんどの行サイズよりもはるかに大きいため、極端な例です。したがって、BLOCKS(USER_TABLES内)がより良いガイドになる可能性があります。
しかし、テーブルに200,000行があり、それらの半分を削除した場合、テーブルは同じ数のブロックを「所有」します。他のテーブルで使用するために解放されません。また、ブロックはテーブルに個別に追加されるのではなく、「エクステント」と呼ばれるグループで追加されます。そのため、通常はテーブルにEMPTY_BLOCKS(これもUSER_TABLESにあります)があります。
分割テーブルの修正:
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 ;
これはもう少し正確であることがわかりました:
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
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 ;
テーブルデータ、テーブルインデックス、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;
ソース。