Làm cách nào để tính kích thước bảng trong Oracle


128

Đã quen với (và có khả năng bị làm hỏng bởi) MSSQL, tôi tự hỏi làm thế nào tôi có thể nhận được ở kích thước bảng trong Oracle 10g. Tôi đã googled nó vì vậy bây giờ tôi biết rằng tôi có thể không có tùy chọn dễ dàng như sp_spaceuse. Vẫn là những câu trả lời tiềm năng mà tôi nhận được hầu hết thời gian đã lỗi thời hoặc không hoạt động. Có lẽ bởi vì tôi không có DBA trên lược đồ mà tôi đang làm việc.

Bất cứ ai sẽ có giải pháp và hoặc khuyến nghị?


nếu có một câu trả lời cho câu trả lời bị làm hỏng, thì hãy lấy câu trả lời bạn nhận được từ đây và gói chúng vào một thủ tục và gọi nó là ... dun dun duh ... sp_spaceuse. Có rất ít phép thuật đối với nó.

1
@MarkBrady Có lẽ không phải ảo thuật, nhưng một tấn kiến thức phức tạp là bắt buộc.
jpmc26

Câu trả lời:


201

Bạn có thể quan tâm đến truy vấn này. Nó cho bạn biết có bao nhiêu không gian được phân bổ cho mỗi bảng có tính đến các chỉ mục và bất kỳ LOB nào trên bảng. Thường thì bạn muốn biết "Bảng mua hàng chiếm bao nhiêu khoảng trống, bao gồm mọi chỉ mục" thay vì chỉ bảng. Bạn luôn có thể đi sâu vào chi tiết. Lưu ý rằng điều này yêu cầu quyền truy cập vào các chế độ xem 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
Lưu ý rằng câu trả lời này tính các phân đoạn, không phân biệt giữa không gian hiện đang sử dụng so với không gian trước đây được sử dụng. Rõ ràng, một khi một phân đoạn được gán cho một bảng, nó luôn được gán cho một bảng, ngay cả khi không gian được giải phóng. Xem ở đây . Tôi đoán bạn phải đi xuống mức độ để xem có bao nhiêu không gian thực sự được sử dụng ?
jpmc26

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.
;

Lưu ý: Đây là các ước tính, được thực hiện chính xác hơn với thu thập số liệu thống kê:

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

2
Các thống kê này có thể là null( num_rows, avg_row_len), bạn cần thực hiện một số phân tích trước khi thông qua tuyên bố sauANALYZE TABLE your_table COMPUTE STATISTICS
Brice

Phân tích khó khăn này có thể rất dài!
Brice

công việc tuyệt vời khi tôi không thể kiểm tra bảng không có bảng
tungns304

30

Trước hết, tôi thường cảnh báo rằng việc thu thập số liệu thống kê bảng để thực hiện phân tích không gian là một điều nguy hiểm tiềm tàng phải làm. Thu thập số liệu thống kê có thể thay đổi kế hoạch truy vấn, đặc biệt nếu DBA đã định cấu hình công việc thu thập số liệu thống kê sử dụng các tham số không mặc định mà cuộc gọi của bạn không sử dụng và sẽ khiến Oracle phân tích lại các truy vấn sử dụng bảng trong câu hỏi có thể là hiệu suất đánh. Nếu DBA đã cố tình để lại một số bảng mà không có số liệu thống kê (phổ biến nếu bạn OPTIMIZER_MODElà CHỌN), việc thu thập số liệu thống kê có thể khiến Oracle ngừng sử dụng trình tối ưu hóa dựa trên quy tắc và bắt đầu sử dụng trình tối ưu hóa dựa trên chi phí cho một nhóm truy vấn có thể là hiệu suất chính đau đầu nếu nó được thực hiện bất ngờ trong sản xuất. Nếu số liệu thống kê của bạn là chính xác, bạn có thể truy vấn USER_TABLES( ALL_TABLEShoặcDBA_TABLES) trực tiếp mà không cần gọi GATHER_TABLE_STATS. Nếu số liệu thống kê của bạn không chính xác, có thể có một lý do cho điều đó và bạn không muốn làm phiền hiện trạng.

Thứ hai, tương đương gần nhất với sp_spaceusedthủ tục SQL Server có khả năng là DBMS_SPACEgói của Oracle . Tom Kyte có một show_spacequy trình tốt đẹp cung cấp giao diện đơn giản cho gói này và in ra thông tin tương tự như những gì được sp_spaceusedin ra.


8

Đầu tiên, thu thập số liệu thống kê tối ưu hóa trên bàn (nếu bạn chưa có):

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

CẢNH BÁO: Như Justin nói trong câu trả lời của mình, việc thu thập số liệu thống kê tối ưu hóa ảnh hưởng đến tối ưu hóa truy vấn và không nên được thực hiện mà không có sự quan tâm và cân nhắc đúng mức !

Sau đó tìm số khối bị chiếm bởi bảng từ số liệu thống kê được tạo:

select blocks, empty_blocks, num_freelist_blocks
from   all_tables
where  owner = 'MYSCHEMA'
and    table_name = 'MYTABLE';
  • Tổng số khối được phân bổ cho bảng là các khối + blank_blocks + num_freelist_blocks.

  • khối là số khối thực sự chứa dữ liệu.

Nhân số khối với kích thước khối đang sử dụng (thường là 8KB) để có được không gian tiêu thụ - ví dụ: 17 khối x 8KB = 136KB.

Để làm điều này cho tất cả các bảng trong một lược đồ cùng một lúc:

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

select table_name, blocks, empty_blocks, num_freelist_blocks
from   user_tables;

Lưu ý: Thay đổi được thực hiện ở trên sau khi đọc chủ đề AskTom này


7

Tôi đã sửa đổi truy vấn của WW để cung cấp thông tin chi tiết hơn:

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

Đối với các bảng và chỉ mục được phân vùng phụ, chúng ta có thể sử dụng truy vấn sau



    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 các bảng bạn cần là DBA_TABLES, DBA_EXTENT hoặc DBA_SEGITT và DBA_DATA_FILES. Ngoài ra còn có các phiên bản USER_ và ALL_ cho các bảng mà bạn có thể xem nếu bạn không có quyền quản trị trên máy.


4

Đây là một biến thể của câu trả lời WW, nó bao gồm các phân vùng và phân vùng phụ như những người khác ở trên đã đề xuất, cộng với một cột để hiển thị TYPE: Table / Index / LOB, v.v.

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

Tôi đã sửa đổi truy vấn để có được kích thước lược đồ trên mỗi vùng bảng ..

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

Phụ thuộc vào ý của bạn bởi "kích thước của bảng". Một bảng không liên quan đến một tệp cụ thể trên hệ thống tệp. Một bảng sẽ nằm trên một không gian bảng (có thể là nhiều không gian bảng nếu nó được phân vùng và có thể nhiều không gian bảng nếu bạn cũng muốn đưa vào các chỉ mục tài khoản trên bảng). Một không gian bảng thường sẽ có nhiều bảng trong đó và có thể được trải rộng trên nhiều tệp.

Nếu bạn đang ước tính cần bao nhiêu dung lượng cho sự tăng trưởng trong tương lai của bảng, thì avg_row_len nhân với số lượng hàng trong bảng (hoặc số hàng bạn mong đợi trong bảng) sẽ là một hướng dẫn tốt. Nhưng Oracle sẽ để lại một số không gian trống trên mỗi khối, một phần để cho phép các hàng 'phát triển' nếu chúng được cập nhật, một phần vì không thể phù hợp với toàn bộ một hàng khác trên khối đó (ví dụ: khối 8K chỉ phù hợp với 2 hàng 3K, mặc dù đó sẽ là một ví dụ cực đoan vì 3K lớn hơn nhiều so với hầu hết các kích thước hàng). Vì vậy, BLOCK (trong USER_TABLES) có thể là một hướng dẫn tốt hơn.

Nhưng nếu bạn có 200.000 hàng trong một bảng, đã xóa một nửa trong số chúng, thì bảng vẫn sẽ 'sở hữu' cùng số khối. Nó không giải phóng chúng cho các bảng khác sử dụng. Ngoài ra, các khối không được thêm vào một bảng riêng lẻ, nhưng trong các nhóm được gọi là 'phạm vi'. Vì vậy, thường sẽ có EMPTY_BLOCKS (cũng trong USER_TABLES) trong một bảng.


1

Sửa lỗi cho các bảng được phân đoạn:

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

Chọn đơn giản trả về kích thước thô của các bảng, dựa trên kích thước khối, cũng bao gồm kích thước với chỉ mục

chọn tên_bảng Kích thước bảng từ thứ tự dba_tables bằng 3


0

Tôi thấy điều này chính xác hơn một chút:

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
Trông hơi giống câu trả lời của tôi?
Thế chiến.

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

có thêm một tùy chọn cho phép lấy kích thước "chọn" với các phép nối và kích thước bảng cũng là tùy chọn

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

Tôi có cùng một biến thể như các biến thể cuối cùng tính toán các phân đoạn của dữ liệu bảng, chỉ mục bảng và các trường 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;

Nguồn .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.