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
패키지 일 가능성이 높습니다 . Tom Kyte는 이 패키지에 간단한 인터페이스를 제공하고 출력되는 것과 유사한 정보를 출력 하는 훌륭한 show_space
절차 를 가지고 sp_spaceused
있습니다.
먼저 테이블에서 옵티 마이저 통계를 수집하십시오 (아직없는 경우).
begin
dbms_stats.gather_table_stats('MYSCHEMA','MYTABLE');
end;
/
경고 : Justin의 답변에서 옵티 마이저 통계 수집은 쿼리 최적화에 영향을 미치며 적절한주의와 고려없이 수행하면 안됩니다. !
그런 다음 생성 된 통계에서 테이블이 차지하는 블록 수를 찾으십시오.
select blocks, empty_blocks, num_freelist_blocks
from all_tables
where owner = 'MYSCHEMA'
and table_name = 'MYTABLE';
테이블에 할당 된 총 블록 수는 블록 + empty_blocks + num_freelist_blocks입니다.
블록은 실제로 데이터를 포함하는 블록의 수입니다.
사용 된 공간 (예 : 17 블록 x 8KB = 136KB)을 얻으려면 사용중인 블록 크기 (일반적으로 8KB)를 블록 수에 곱하십시오.
한 번에 스키마의 모든 테이블에 대해이를 수행하려면 다음을 수행하십시오.
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 답변의 변형은 여기에 다른 사람들이 제안한 파티션 및 하위 파티션과 유형을 표시하는 열이 포함됩니다. 테이블 / 색인 / 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에 테이블의 행 수 (또는 테이블에 예상되는 행 수)를 곱한 것이 좋습니다. 그러나 오라클은 각 블록에 여유 공간을 남겨두고 부분적으로 업데이트 될 경우 행이 '증가'할 수 있도록 허용합니다. 부분적으로는 해당 블록의 다른 전체 행을 맞추는 것이 불가능할 수 있기 때문입니다 (예 : 8K 블록은 2 행에만 적합 함) 3K는 대부분의 행 크기보다 훨씬 크므로 극단적 인 예입니다). 따라서 USER_TABLES의 BLOCKS가 더 나은 가이드가 될 수 있습니다.
그러나 테이블에 200,000 개의 행이 있고 그 중 절반을 삭제하면 테이블은 여전히 같은 수의 블록을 '소유'합니다. 다른 테이블에서 사용할 수 있도록 해제하지 않습니다. 또한 블록은 개별적으로 테이블에 추가되는 것이 아니라 'extent'라는 그룹으로 추가됩니다. 따라서 일반적으로 테이블에 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 ;
조인으로 "선택"크기를 얻을 수있는 옵션과 옵션으로 테이블 크기를 추가 할 수있는 옵션이 하나 더 있습니다.
-- 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);
테이블 데이터, 테이블 인덱스 및 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;
소스 .