Oracle-仅选择包含数据的列

时间:2019-02-14 15:01:43

标签: oracle oracle11g

我们有一个由第三方建立的包含大量表和列的数据库。

这些列中有许多是完全未使用的。我正在尝试创建一个查询,该查询返回实际使用的所有列的列表(包含> 0个值)。

我当前的尝试-

SELECT table_name, column_name
FROM ALL_TAB_COLUMNS
WHERE OWNER = 'XUSER' 
    AND num_nulls < 1
;

按预期使用num_nulls < 1大大减少了返回值的数量。

但是,在检查某些表时,查询结果中缺少某些列,其中似乎包含值。

有人可以解释为什么会这样吗?

2 个答案:

答案 0 :(得分:1)

首先,统计信息并不总是100%准确。由于它们毕竟是统计信息,因此可以将它们收集在表行的子集上。就像民意测验员不必询问每个美国人对给定的政客的感觉一样,Oracle只需读取表中的一部分数据,就可以对表中的数据有足够的准确了解。

即使统计信息收集在表中100%的行上(并且,如果需要,也可以通过这种方式收集 ),只要有任何行,统计信息就会过时在表格上插入,更新或删除。

第二,num_nulls < 1不会告诉您没有数据的列。想象一下一个表,该表包含100行,并且num_nulls等于80的“ X列”。这意味着该列具有20个非空值,但不会通过过滤器。更好的方法(如果您相信统计信息不是陈旧的并且基于100%的行样本),可能是比较DBA_TAB_COLUMNS.NUM_NULLS < DBA_TABLES.NUM_ROWS。例如,在100行表中具有99个null的列的数据在1行中。

答案 1 :(得分:0)

  

“查询结果中缺少某些列,其中似乎包含值。”

可能每个非强制列都可能出现在此集合中,因为某些行可能具有值,但并非所有行。 “某些行”大于零表示这些列不会通过您对num_nulls < 1的测试。

因此,也许您应该搜索未使用的列。该查询将查找每行为空的列:

 select t.table_name
        , tc.column_name
 from user_tables t
      join user_tab_cols tc on t.table_name = tc.table_name
 where t.num_rows > 0
and  t.num_rows = tc.num_nulls;

请注意,如果您正在使用分区,则需要扫描user_tab_partitions.num_rowsuser_part_col_statistics.num_nulls

此外,我第二个人就统计学提出的建议。上面的查询可能会抛出一些误报。我会将从该查询生成的结果视为待进一步调查的候选人列表。例如,您可以生成查询,该查询计算每列的空值的实际数量。