每次ETL作业完成时,我必须为每个表(包括其索引空间)收集实际使用的空间,以及行数。
user_segments和user_extents中的bytes列仅指示分配的空间。所以我使用以下内容来获取每个表的大小
Dbms_Space.object_space_usage (
object_owner => v_owner,
object_name => c.name,
object_type => c.typ,
sample_control => NULL,
space_used => v_space_used_out,
space_allocated => v_space_allocated_out,
chain_pcent => v_chain_pcent_out);
v_space_used := v_space_used+v_space_used_out;
v_space_allocated := v_space_allocated+v_space_allocated_out;
循环遍历每个索引和表本身。
我的问题是在我运行上面的代码之前是否有必要运行?
EXEC DBMS_STATS.GATHER_TABLE_STATS(v_owner,v_table_name);
为什么和/或为什么没有?
谢谢,
答案 0 :(得分:3)
在运行DBMS_SPACE.OBJECT_SPACE_USAGE之前没有必要运行EXEC DBMS_STATS.GATHER_TABLE_STATS(v_owner,v_table_name)
我跑了Dbms_Space.object_space_usage,得到了结果。然后将大量数据插入表中,并再次运行Dbms_Space.object_space_usage。
结果已更新为新的较大值,而不运行GATHER_TABLE_STATS。
我们从Oracle DBMS_SPACE文档中了解到,此程序包需要analyze特权。但是,仅在表上运行OBJECT_SPACE_USAGE时,不会更新all_tables的last_analyzed列。
因此,从观察来看,DBMS_SPACE.OBJECT_SPACE_USAGE似乎对表进行了自己的分析,获得了正确的空间使用。它不依赖于DBMS_STATS收集的更新统计数据,也不会更新统计数据。
进一步证明这一点:
SQL> EXEC DBMS_STATS.delete_table_stats('SOMEOWNER','SOMETABLE');
PL/SQL procedure successfully completed.
SELECT LAST_ANALYZED
FROM ALL_TABLES
WHERE OWNER = 'SOMEOWNER' AND TABLE_NAME = 'SOMETABLE';
LAST_ANALYZED
------------------
SQL>
DECLARE
su NUMBER;
sa NUMBER;
cp NUMBER;
BEGIN
dbms_space.object_space_usage('SOMEOWNER', 'SOMETABLE', 'TABLE',
NULL, su, sa, cp);
dbms_output.put_line('Space Used: ' || TO_CHAR(su));
dbms_output.put_line('Space Allocated: ' || TO_CHAR(sa));
dbms_output.put_line('Chained Percentage: ' || TO_CHAR(cp));
END;
/
Space Used: 1055374677
Space Allocated: 1073741824
Chained Percentage: 0