需要编写一个 sql 脚本来查找 oracle 中任何数据库的元数据详细信息
Posted
技术标签:
【中文标题】需要编写一个 sql 脚本来查找 oracle 中任何数据库的元数据详细信息【英文标题】:Need to write one sql script to find the metadata details of any database in oracle 【发布时间】:2013-02-13 17:21:51 【问题描述】:我的目标是使用 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;
/
【问题讨论】:
粘贴脚本应该不是问题 - 使用 ctrl+K 将代码添加到您的帖子中。至少你可以命名你正在查询的表。 不知何故我添加了脚本..现在请帮助我.. 您有什么要求?您正在查询all_tables
,然后点击user_extents
。您是否假设此脚本将以拥有表的用户身份运行?或者您想为可能不是当前用户模式的特定模式中的所有表运行它?定义表的大小?我们应该排除与表关联的LOB
段吗?物联网的溢出区域?定义行的平均大小。您是否只想将其定义为表段的大小除以表中的行数?
是的...我也可以使用 all_extents..我想将所有者作为文件的输入...我给了 &&1。我们可以排除吊球............不需要......是的
【参考方案1】:
鉴于错误,并且没有看到您的脚本,我猜测您正试图从DBA_TABLES
获取此信息,并且您想使用AVG_ROW_LEN
列但输入的名称错误为AVG_ROW_SIZE
。我的猜测是您正在尝试编写查询
SELECT table_name, num_rows * avg_row_len, avg_row_len
FROM dba_tables
但请注意,DBA_TABLES
中的数据可能不正确。充其量,它是上次在表上收集统计信息时表状态的近似值。但完全有可能从未在表格上收集过统计数据。或者当表的数据量非常少时收集统计信息,现在它有数十亿行。但是,在许多情况下,可以合理地假设统计数据相当准确,并且这些近似值足够接近。当然,您确实希望将OWNER
列添加到查询中,因为单个数据库中可能有许多同名的不同表。
您也可能会被定义绊倒。一张桌子的“平均行长”或“一张桌子的大小”对不同的人来说可能意味着非常不同的东西。例如,如果您的表包含一个外行的LOB
,会发生什么情况?由于LOB
未存储在表的段中,您在计算表的大小时是否计算了LOB
的大小?如果向表中添加一百万个空块,平均行长度会改变吗?如果您想将其定义为表的大小除以行数,则可以。如果您想将其定义为从表中获取一行数据时将返回的平均数据量,则不会。
如果您想要更准确,可以使用DBA_SEGMENTS
表来获取磁盘上各个段的大小。但是,根据您的定义,您可能需要使用其他数据字典表(如 DBA_LOBS
)来确定哪些 LOB 段与特定表相关,以便将它们包含在表大小的计算中。您可以使用DBMS_SPACE
包来获取有关表中空白空间量的信息,如果您想取消它的话。如果您想准确计算表中的行数,则需要执行SELECT COUNT(*) FROM table_name
,这可能会非常昂贵。
【讨论】:
可以将正在编写的脚本通过电子邮件发送给您。这可以给你更多的理解。你能告诉我你的电子邮件地址吗? bcz 对我来说格式更重要,我想将输出写入测试文件。我知道 dba_tables 中的值不准确,所以我需要好的值..bcz 将获取生产数据并将其用作我的其他脚本之一的输入...如果可能,请帮助我。 . @SrikanthGoudLingaala - 随意编辑您的帖子以包含您的脚本。这样其他人,不仅仅是我,也可以看到它。如果您想要更准确的结果,您还需要编辑您的问题以包含您想要使用的“表格大小”和“平均行长度”的精确定义。 现在添加了脚本..请纠正我或让我知道我是否可以写得更好..上面的脚本给出错误...我需要一些该格式的脚本..我想你得到了我的要求。 @Srikanth Goud Lingaala - 你从贾斯汀那里得到答案了吗?为什么您的代码中需要所有这些动态 SQL?为什么在 PL/SQL 中使用“&&1”?这是错误的,只能在 SQL 中使用的替换参数... 我仍然没有得到任何答案...如果我的脚本是错误的..你能帮我写正确的 1 吗?我想你得到了我的要求.....n 使用 th &&1 作为模式名称提供输入【参考方案2】:这是 calc avg row len 的示例:http://www.dba-oracle.com/t_average_row_length.htm 您可以添加其余的...不需要 PL/SQL。
【讨论】:
【参考方案3】:关于 table_size,您应该总结所有分配的块,而不是乘以计算的平均行长度和基于创建的统计信息的行数。只需考虑具有大量删除(除其他外)的未重用块或表。 This and other database related information needed for optimisation is available in QueryAdvisor.
【讨论】:
以上是关于需要编写一个 sql 脚本来查找 oracle 中任何数据库的元数据详细信息的主要内容,如果未能解决你的问题,请参考以下文章