【问题标题】:Query to check the full schema scan for tables in Oracle DB查询以检查 Oracle DB 中表的完整模式扫描
【发布时间】:2020-12-04 15:51:08
【问题描述】:

您好,我需要扫描架构并识别冗余的表(删除的候选),所以我在 DBA_Dependencies 中进行了选择,以检查表是否正在任何 DB 对象类型中使用,例如(过程,包体,视图,物化视图......)我能够找到一些表并排除这些表,因为我还需要捕获总计数,当表最后一次加载/使用时是否有自动方法仅选择选定的表(未在依赖项列表中找到)并捕获计数以及使用/加载的时间

难度 - 这么多桌 500+

我使用了以下查询

查询 1

select table_name, 
       to_number(extractvalue(xmltype(dbms_xmlgen.getxml('select count(*) c from '||owner||'.'||table_name)),'/ROWSET/ROW/C')) as count
from all_tables
where owner = 'SCHEMA_NAME'

查询 2

select owner, table_name, num_rows, sample_size, last_analyzed from all_tables;

查询 1 个结果

过滤表名=CUST_ORDER

OWNER TABLE_NAME COUNT SAMPLE_SIZE LAST_ANALYZED
ABCD  CUST_ORDER  1083     1023       01.01.2020

查询 2 结果

过滤表名=CUST_ORDER

OWNER TABLE_NAME NUM_ROWS SAMPLE_SIZE LAST_ANALYZED
ABCD  CUST_ORDER  1023     1023       01.01.2020

问题

查询 1 - 与查询 2 相比,结果不匹配,因为应用了相同的表和过滤器 在两个查询中以及为什么结果不匹配?

但是当我随机检查其他过滤器是否匹配时,有人知道原因吗?

经过进一步测试,我遇到了一个错误,这个错误表示权限是什么?

ORA-29913: error in executing ODCIEXTTABLEOPEN callout
ORA-29400: data cartridge error
KUP-04040: file **-**.csv in ****_***_***_***** not found
29913. 00000 -  "error in executing %s callout"
*Cause:    The execution of the specified callout caused an error.
*Action:   Examine the error messages take appropriate action.

【问题讨论】:

  • 此错误仅适用于特定架构而不是所有架构

标签: oracle plsql


【解决方案1】:

您在all_tables 上看到的数字是对行数的时间点捕获。只有在为该表重建统计信息时才会更新它。

这是一个例子:

CREATE TABLE t1 AS
SELECT *
  FROM all_objects;

SELECT t.num_rows
  FROM all_tables t
 WHERE t.table_name = 'T1';
-- 78570

SELECT COUNT(*)
  FROM t1;
-- 78570

统计数据和物理行数匹配!

INSERT INTO t1
  SELECT *
    FROM all_objects ao
   WHERE rownum <= 5;
-- 5 rows inserted

SELECT t.num_rows
  FROM all_tables t
 WHERE t.table_name = 'T1';
-- 78570

SELECT COUNT(*)
  FROM t1;
-- 78575

这里出现了不匹配的情况,因为插入了行(甚至可能删除了行),但表的统计信息尚未更新。让我们更新它们:

BEGIN
  dbms_stats.gather_table_stats(ownname => 'SCHEMA',
                                tabname => 'T1');
END;
/

SELECT t.num_rows
  FROM all_tables t
 WHERE t.table_name = 'T1';
-- 78575

现在您可以看到行匹配。使用来自 all_tables 的值可能足以满足您的研究需求(而且查询肯定会比计算每个表更快)。

【讨论】:

  • 非常感谢您举例说明,这很有帮助
【解决方案2】:

Query - 1 是表的实际数据,因此是准确的数据。可以依赖此查询的输出。

查询 - 2 不是实际数据。它是上次分析表时捕获的数据,不应依赖此查询来查找表中的记录数。

您可以收集此表上的统计信息并执行 query-2,然后您将找到与 query-1 相同的数据

如果在收集统计信息后没有从表中插入或删除记录,则查询 1 和查询 2 数据将匹配该表。

【讨论】:

  • 非常感谢这是简单明了的解释
  • @rakseh 统计数据也是使用抽样过程收集的。在默认设置下,dbms_stats 可能会读取所有行并捕获确切的计数,或者它可能决定使用较小的样本并向上推断。统计数据只需要足够接近,优化器就可以选择最佳方法,并且不需要每次都与实际计数匹配。
  • @WilliamRobertson 从 11g 开始,默认的统计信息收集选项使用 Number of Distinct Values 算法来扫描整个表并始终返回准确的行数。 (尽管其他统计信息,如直方图,可能会使用单独的传递和采样。)
  • @JonHeller 我注意到它倾向于给出准确的计数,但我不知道它是否有保证。谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-08-27
  • 1970-01-01
  • 2021-05-25
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-21
相关资源
最近更新 更多