-1

我的目标是使用 PL/SQL 在 Oracle 中编写一个脚本,以从以下格式的数据库表中获取数据。

table_name|table_size|avg_row_length

我需要数据库中所有可用的表。以下是尝试编写以获取特定架构的上述详细信息的脚本。但是我得到以下错误

PLS-00103:在预期以下情况之一时遇到符号“AVG_ROW_SIZE”::=; 不为空默认字符

SET serveroutput on;
clear screen;

set lin 20000;
set trimspool on;
set feed off;
set verify off;
set head off;

spool &&1..metadata_report.out

DECLARE
    v_tbl_name   VARCHAR2(1500);
    v_row_num    NUMBER(20);
    table_size   NUMBER(20);
    avg_row_size NUMBER(30);
    CURSOR c1 IS
      SELECT DISTINCT table_name
      FROM   all_tables
      WHERE  owner = Upper('&&1')
      ORDER  BY table_name ASC;
    c1_rec       c1%ROWTYPE;
BEGIN
    OPEN c1;

    LOOP
        FETCH c1 INTO c1_rec;

        exit WHEN c1%NOTFOUND;

        EXECUTE IMMEDIATE
'select sum((bytes/1024)) from user_extents where segment_name = "'||c1_rec.table_name||'"' INTO
table_size;

EXECUTE IMMEDIATE
'select decode(count(*),NULL,0, count(*)) FROM &&1.."'||c1_rec.table_name||'"'
    INTO v_row_num;

IF( v_row_num = 0 ) THEN
  avg_row_size := 0;
ELSE
  EXECUTE IMMEDIATE 'SELECT table_size/v_row_num FROM DUAL' INTO avg_row_size;
END IF;

dbms_output.Put_line(c1_rec.table_name
                     ||'|'
                     ||table_size
                     ||'|'
                     ||avg_row_size);
END LOOP;

CLOSE c1;
END; 

/
4

3 回答 3

2

Given the error, and without seeing your script, my guess is that you are trying to get this information from DBA_TABLES and that you want to use the AVG_ROW_LEN column but have typed the name incorrectly as AVG_ROW_SIZE. My guess is that you are trying to write the query

SELECT table_name, num_rows * avg_row_len, avg_row_len
  FROM dba_tables

Be aware, however, that the data in DBA_TABLES may be incorrect. At best, it is an approximation of the state of the table the last time that statistics were gathered on the table. But it is entirely possible that statistics were never gathered on the table. Or that statistics were gathered when the table had a very small amount of data and now it has billions of rows. For many situations, though, it's reasonable to assume that the statistics are reasonably accurate and that these approximate values will be close enough. Of course, you'd really want to add the OWNER column to the query since there can be many different tables with the same name in a single database.

You may also get tripped up by definitions. The "average row length" of a table or the "size of a table" can mean very different things to different people. What happens, for example, if your table contains an out-of-line LOB? Do you count the size of the LOB when you are calculating the size of the table since the LOB is not stored in the table's segment? Does the average row length change if you add a million empty blocks to your table? It does if you want to define it as the size of the table divided by the number of rows. It doesn't if you want to define it as the average amount of data that would be returned if you fetched one row of data from the table.

If you want more accuracy, you can use the DBA_SEGMENTS table to get the size of the various segments on disk. Depending on your definitions, though, you may need to use other data dictionary tables like DBA_LOBS to figure out which LOB segments are related to a particular table in order to include them in the calculation for the size of the table. You can use the DBMS_SPACE package to get information about the amount of empty space in the table should you want to back that out. If you want to get an accurate count of the number of rows in the table, you'd need to do a SELECT COUNT(*) FROM table_name which would potentially be quite expensive.

于 2013-02-13T18:05:45.823 回答
0

关于 table_size,您应该总结所有分配的块,而不是乘以计算的平均行长度和基于创建的统计信息的行数。只需考虑具有大量删除(除其他外)的未重用块或表。QueryAdvisor 中提供了优化所需的此信息和其他与数据库相关的信息。

于 2013-09-28T12:58:26.803 回答
0

这是 calc avg row len 的示例:http ://www.dba-oracle.com/t_average_row_length.htm 您可以添加其余部分...不需要 PL/SQL。

于 2013-02-13T17:50:10.017 回答