我们有一个由第三方建立的包含大量表和列的数据库。
这些列中有许多是完全未使用的。我正在尝试创建一个查询,该查询返回实际使用的所有列的列表(包含> 0个值)。
我当前的尝试-
SELECT table_name, column_name
FROM ALL_TAB_COLUMNS
WHERE OWNER = 'XUSER'
AND num_nulls < 1
;
按预期使用num_nulls < 1
大大减少了返回值的数量。
但是,在检查某些表时,查询结果中缺少某些列,其中似乎包含值。
有人可以解释为什么会这样吗?
答案 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_rows
和user_part_col_statistics.num_nulls
。
此外,我第二个人就统计学提出的建议。上面的查询可能会抛出一些误报。我会将从该查询生成的结果视为待进一步调查的候选人列表。例如,您可以生成查询,该查询计算每列的空值的实际数量。