正德厚生,臻于至善

综合统计 Oracle 表行数、表大小、索引大小及 LOB 大小的 SQL

--综合统计 Oracle 表行数、表大小、索引大小及 LOB 大小的 SQL 1
SELECT
dt.owner,
dt.table_name,
dt.num_rows AS 行数,
ROUND(SUM(CASE WHEN ds.segment_type = 'TABLE' THEN ds.bytes ELSE 0 END)/1024/1024, 2) AS 表大小_MB,
ROUND(SUM(CASE WHEN ds.segment_type = 'INDEX' THEN ds.bytes ELSE 0 END)/1024/1024, 2) AS 索引大小_MB,
ROUND(SUM(CASE WHEN ds.segment_type = 'LOBSEGMENT' THEN ds.bytes ELSE 0 END)/1024/1024, 2) AS LOB大小_MB
FROM
dba_tables dt
LEFT JOIN dba_segments ds ON dt.owner = ds.owner AND (ds.segment_name = dt.table_name OR ds.segment_name IN (SELECT index_name FROM dba_indexes WHERE table_owner = dt.owner AND table_name = dt.table_name) OR ds.segment_name IN (SELECT segment_name FROM dba_lobs WHERE owner = dt.owner AND table_name = dt.table_name))
GROUP BY dt.owner, dt.table_name, dt.num_rows;

不过这样可能效率不高,因为JOIN条件复杂。可能需要分开处理表、索引和LOB,然后合并结果。

另一种方法是分别统计表、索引和LOB的大小,然后通过子查询或CTE将它们合并。例如:

--综合统计 Oracle 表行数、表大小、索引大小及 LOB 大小的 SQL 2
WITH
table_size AS (
SELECT owner, segment_name AS table_name, SUM(bytes) AS bytes
FROM dba_segments
WHERE segment_type = 'TABLE'
GROUP BY owner, segment_name
),
index_size AS (
SELECT i.table_owner AS owner, i.table_name, SUM(s.bytes) AS bytes
FROM dba_indexes i
JOIN dba_segments s ON i.owner = s.owner AND i.index_name = s.segment_name
WHERE s.segment_type = 'INDEX'
GROUP BY i.table_owner, i.table_name
),
lob_size AS (
SELECT l.owner, l.table_name, SUM(s.bytes) AS bytes
FROM dba_lobs l
JOIN dba_segments s ON l.owner = s.owner AND l.segment_name = s.segment_name
GROUP BY l.owner, l.table_name
)
SELECT
dt.owner,
dt.table_name,
dt.num_rows AS 行数,
ROUND(COALESCE(ts.bytes, 0)/1024/1024, 2) AS 表大小_MB,
ROUND(COALESCE(isz.bytes, 0)/1024/1024, 2) AS 索引大小_MB,
ROUND(COALESCE(ls.bytes, 0)/1024/1024, 2) AS LOB大小_MB
FROM
dba_tables dt
LEFT JOIN table_size ts ON dt.owner = ts.owner AND dt.table_name = ts.table_name
LEFT JOIN index_size isz ON dt.owner = isz.owner AND dt.table_name = isz.table_name
LEFT JOIN lob_size ls ON dt.owner = ls.owner AND dt.table_name = ls.table_name
WHERE
dt.owner = '用户名称' AND dt.table_name = '表名';

这种方法可能更清晰,且效率更高。同时,每个部分单独处理,便于理解和维护。
需要验证各部分的正确性。表大小直接从dba_segments中segment_type='TABLE'获取。索引大小需要关联dba_indexes和dba_segments,确保索引属于该表。LOB大小则通过dba_lobs找到对应的segment_name,再连接dba_segments。
此外,num_rows需要统计信息准确,可能需要提醒用户先执行统计信息收集,或者在查询中包含提示。
最后,权限方面,确保用户有访问dba_tables、dba_segments、dba_indexes和dba_lobs的权限,否则替换为user_*视图。
综上,最终的SQL可能采用CTE方式,结构清晰,各部分分别统计后合并,确保正确获取表、索引和LOB的大小。

-- 执行前确保统计信息更新(可选)  
EXEC DBMS_STATS.GATHER_TABLE_STATS(ownname => '用户名称', tabname => '表名', cascade => TRUE);  

--综合统计 Oracle 表行数、表大小、索引大小及 LOB 大小的 SQL 3
SELECT  
    dt.owner AS 用户,  
    dt.table_name AS 表名,  
    dt.num_rows AS 行数,  
    ROUND(NVL(ts.table_bytes, 0)/1024/1024, 2) AS 表大小_MB,  
    ROUND(NVL(idx.index_bytes, 0)/1024/1024, 2) AS 索引大小_MB,  
    ROUND(NVL(lob.lob_bytes, 0)/1024/1024, 2) AS LOB大小_MB  
FROM  
    dba_tables dt  
LEFT JOIN (  
    SELECT owner, segment_name, SUM(bytes) AS table_bytes  
    FROM dba_segments  
    WHERE segment_type = 'TABLE'  
    GROUP BY owner, segment_name  
) ts  
    ON dt.owner = ts.owner AND dt.table_name = ts.segment_name  
LEFT JOIN (  
    SELECT table_owner, table_name, SUM(bytes) AS index_bytes  
    FROM dba_indexes i  
    JOIN dba_segments s  
        ON i.owner = s.owner AND i.index_name = s.segment_name  
    WHERE s.segment_type = 'INDEX'  
    GROUP BY table_owner, table_name  
) idx  
    ON dt.owner = idx.table_owner AND dt.table_name = idx.table_name  
LEFT JOIN (  
    SELECT l.owner, l.table_name, SUM(s.bytes) AS lob_bytes  
    FROM dba_lobs l  
    JOIN dba_segments s  
        ON l.owner = s.owner AND l.segment_name = s.segment_name  
    GROUP BY l.owner, l.table_name  
) lob  
    ON dt.owner = lob.owner AND dt.table_name = lob.table_name  
WHERE  
    dt.owner = '用户名称'  
    AND dt.table_name = '表名';  

关键逻辑说明
‌行数统计‌:
从 dba_tables.num_rows 获取表行数,依赖统计信息准确性‌14。
‌表大小‌:
通过 dba_segments 中 segment_type='TABLE' 的 bytes 字段统计物理存储空间‌。
‌索引大小‌:
关联 dba_indexes 和 dba_segments,筛选 segment_type='INDEX' 的索引段统计‌。
‌LOB 大小‌:
通过 dba_lobs 关联 dba_segments,获取 LOB 字段的独立存储段大小‌。
注意事项
‌权限要求‌:需有 SELECT 权限访问 dba_tables、dba_segments、dba_indexes 和 dba_lobs;普通用户可替换为 user_* 视图‌。
‌统计信息更新‌:若 num_rows 为空或不准确,需执行 DBMS_STATS.GATHER_TABLE_STATS‌14。
‌结果差异‌:
物理存储大小(dba_segments.bytes)包含未使用的预分配块,可能大于实际数据占用‌23。
索引和 LOB 字段的大小仅统计与当前表关联的对象‌12。
扩展场景
‌批量统计用户下所有表‌:移除 WHERE 条件并添加 ORDER BY 排序‌。
‌LOB 字段详情‌:可单独查询 dba_lobs 和 dba_segments 获取字段级存储分布‌。
赞(0) 打赏
未经允许不得转载:徐万新之路 » 综合统计 Oracle 表行数、表大小、索引大小及 LOB 大小的 SQL

支持快讯、专题、百度收录推送、人机验证、多级分类筛选器,适用于垂直站点、科技博客、个人站,扁平化设计、简洁白色、超多功能配置、会员中心、直达链接、文章图片弹窗、自动缩略图等...

联系我们

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册