如何确定非分区表高水位虚高
如何确定非分区表高水位虚高:
一般认为分配给表使用的数据块空间远大于表实际占用存储空间时,我们就认为表的高水位虚高,涉及该表的查询sql存在不必要的消耗,需要进行优化。
通过比较数据占用和分配数据块的空间比对来确定哪些表的高水位虚高:
sys用户执行(如果数据库支持statistics_level配置,一般9.2之后都支持):
SQL>exec dbms_stats.FLUSH_DATABASE_MONITORING_INFO();
再执行:
SELECT a.owner || '.' || a.table_name "Table", a.num_rows, a.avg_row_len, b.inserts, b.deletes, a.num_rows + nvl(b.inserts, 0) - nvl(b.deletes, 0) total_rows, round(a.avg_row_len *(a.num_rows + nvl(b.inserts, 0) - nvl(b.deletes, 0)) / 1024 / 1024,4) "Calculate_Sizle(Mb)估算的大小", c.bytes / 1024 / 1024 "Segment_Size(Mb)段大小", (a.avg_row_len * (a.num_rows + nvl(b.inserts, 0) - nvl(b.deletes, 0))) /c.bytes "使用率" FROM dba_tables a LEFT JOIN all_tab_modifications b ON a.owner = b.table_owner AND a.table_name = b.table_name INNER JOIN dba_segments c ON a.owner = c.owner AND a.table_name = c.segment_name WHERE a.last_analyzed IS NOT NULL AND a.partitioned = 'NO' --AND b.deletes > 0 AND a.owner LIKE '%DLP114_SXU01%' AND a.table_name LIKE 'DEBUG_MSG' --AND c.bytes / 1024 / 1024 > 100 --AND (a.avg_row_len * (a.num_rows + nvl(b.inserts, 0) - nvl(b.deletes, 0))) / c.bytes < 0.3 ORDER BY b.deletes DESC;
注意: 如果数据库不支持statistics_level配置的话,请使用数据库用户对表单独执行ANALYZE后查看。
Sql中关键条件说明:
avg_row_len * (a.num_rows + nvl(b.inserts, 0) - nvl(b.deletes, 0))) / c.bytes < 0.3:表单条数据的平均占用空间*当前数据条数=表数据理论占用数据块大小,c.byte是表实际占用的数据块大小。用这两个比率来分析出表占用的数据块的实际使用率。
c.bytes / 1024 / 1024 > 100:表实际占用数据块大小,对于表实际占用很小的表来说,认为消耗是可以接受的,可以认为不具优化价值,可以选择忽略这些表的虚高。