尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
数据库表大小查询实战:MySQL、Oracle、SQL Server、PostgreSQL 命令汇总
屠龙刀法系列到这篇已经是第三十六篇了本来想写点更冷门的东西但后台好几个读者都在问同一个问题怎么查看不同数据库的表格大小。这个问题表面上很基础真遇到的时候才麻烦。换库排障要查磁盘快满要查做数据迁移要评估同步方案也要查甚至连面试都会被问一嘴。麻烦就麻烦在“不同数据库”四个字。MySQL 有 information_schemaOracle 有数据字典视图SQL Server 有自己的存储过程PostgreSQL 又是一套函数。命令完全不通用现场翻文档又来不及。这篇就把我这些年实际用过的办法都整理出来按数据库类型拆开讲每个都给可以直接复制的命令顺带把统计口径、常见坑也一并说清楚。1. 为什么查表格大小先搞懂存储逻辑1.1 数据库是怎么把表格“存”进磁盘的很多人以为查表大小就是“数一下数据量”其实不是。数据库落盘的最小单位是页Page或块BlockMySQL InnoDB 默认一页 16KBOracle 默认一个块 8KBSQL Server 默认一页 8KBPostgreSQL 默认一个块 8KB。数据行按顺序塞进这些页里页再组成区Extent区再组成段Segment段最终落在表空间对应的数据文件上。用书架来类比就好懂了表是“书的内容”表空间是“书架”数据文件是“一本本实体书”页就是“每一页纸”。你问“这张表多大”本质上是问“这本书的内容加上目录、附录总共占了几页纸、占了多少个书架格子”。这里有个最常见的误区以为表大小只跟行数有关。实际上索引占了相当大的空间尤其是有多个二级索引的表索引体积可能超过数据本身。MySQL 里主键索引和数据是放在一起的InnoDB 聚簇索引二级索引单独存Oracle 和 PostgreSQL 里索引和数据完全分离SQL Server 的堆表和聚集索引表也不一样。所以查表大小时一定要区分“数据大小”和“索引大小”两个加起来才是完整答案。1.2 逻辑大小和物理大小不是一回事系统视图里查出来的表大小我习惯叫它“逻辑大小”。它的计算逻辑是统计某某段有多少个页/块然后乘以页大小。但“逻辑大小”和你在操作系统里看到的实际文件大小常常对不上。举例来说MySQL 一张 InnoDB 表删掉一半数据.ibd 文件大小可能纹丝不动Oracle 表 DELETE 大量数据后段空间也不会自动收缩SQL Server 表的碎片率高了实际占用的盘可能比逻辑大小还大。因为数据库为了性能通常会预分配空间或者把已删除数据标记为“可复用”并不会立刻还给操作系统。所以当你用系统视图查出来的数字和ls -lh看到的文件大小不一致时别急着怀疑命令写错了。搞清楚两类口径的差异后面排查问题会省很多时间。真正的物理空间占用要看数据文件本身你可管理、可分析的空间占用看系统视图就够。2. MySQL最常用也最容易踩坑的一个2.1 核心查询一条 SQL 看全所有表大小MySQL 查看表格大小主要靠information_schema.tables这个系统库里面每一行对应一张表关键字段有这几个table_schema库名table_name表名engine存储引擎常见 InnoDB、MyISAMtable_rows估计行数注意只是估计值不一定准data_length数据部分占用的字节数InnoDB 里包含聚簇索引index_length索引部分占用的字节数InnoDB 里指二级索引data_free已分配但未使用的空间也就是碎片查单库大小时这么写SELECT table_name, engine, table_rows, ROUND((data_length index_length) / 1024 / 1024, 2) AS total_size_mb, ROUND(data_length / 1024 / 1024, 2) AS data_size_mb, ROUND(index_length / 1024 / 1024, 2) AS index_size_mb FROM information_schema.tables WHERE table_schema your_db ORDER BY (data_length index_length) DESC;把your_db换成自己的库名跑完就能看到每张表的大小从大到小排列。data_length index_length是表占用的总字节数除以两次 1024 就是 MB。我习惯再加一个LIMIT 20只取前 20 张大表日常巡检完全够用。这里注意一下MyISAM 表的data_length只算数据文件.MYI索引文件走index_lengthInnoDB 因为聚簇索引就是数据本身所以data_length是“数据页 主键索引页”的总和。不同引擎的字段含义略有区别但加在一起看整体大小不会出错。2.2 按库汇总和找物理文件大小如果是给整个实例做容量规划光看单张表还不够要按库汇总。一条简单 SQL 就行SELECT table_schema, ROUND(SUM(data_length index_length) / 1024 / 1024, 2) AS db_size_mb, ROUND(SUM(data_length) / 1024 / 1024, 2) AS data_size_mb, ROUND(SUM(index_length) / 1024 / 1024, 2) AS index_size_mb FROM information_schema.tables GROUP BY table_schema ORDER BY db_size_mb DESC;这个结果能直观告诉你每个库占了多大空间哪个库增长快做资源分配时心里有数。如果觉得逻辑大小不够“落地”想看物理文件大小Linux 上直接看数据目录就行。MySQL 8.0 默认每张表独立表空间文件命名一般是库名/表名.ibddu -sh /var/lib/mysql/your_db/your_table.ibd ls -lh /var/lib/mysql/your_db/your_table.ibd如果历史库用了共享表空间或者开启了innodb_file_per_tableOFF那所有表的数据都在ibdata1里没法按表看物理文件这种情况只能以系统视图为准。另外提醒一句table_rows在 InnoDB 里是按采样算出来的经常和实际行数差很远。真要精确统计行数别信这个字段老老实实SELECT COUNT(*) FROM your_table;在小表上无所谓大表上也得接受这个代价。2.3 统计信息不刷新怎么办我遇到最多的问题是刚灌了一大批数据进去再用information_schema.tables查大小根本没变化。这不是命令错是统计信息还没更新。InnoDB 的统计信息更新机制比较复杂受innodb_stats_auto_recalc、innodb_stats_persistent这些参数影响。表数据大面积变化后统计信息不一定立刻同步。手动刷新很简单ANALYZE TABLE your_table;跑完再查数据一般就变了。ANALYZE TABLE本身也会消耗一些 IO大表执行时要注意避开业务高峰。还有一种情况information_schema.tables里data_length统计的是“已分配的空间”不代表“实际有效数据量”。表因为大量删除产生碎片后已分配空间会明显大于实际数据量。这时候想要紧凑的数据大小要么OPTIMIZE TABLE your_table;重建表回收空间要么接受这个误差。在同一套对比逻辑下趋势分析还是能用的。3. Oracle 和国产数据库段Segment视角3.1 用 user_segments / dba_segments 查表大小Oracle 和 MySQL 的思路完全不一样。MySQL 看的是“表”这个逻辑对象Oracle 更底层一点看的是“段Segment”。一张表是一个表段一个索引是一个索引段一个 LOB 字段也有自己的段。表空间由若干个段组成段又由区组成区是连续页的集合。查当前用户下表所占空间最简单的是查user_segmentsSELECT segment_name, segment_type, ROUND(bytes / 1024 / 1024, 2) AS size_mb FROM user_segments WHERE segment_type TABLE ORDER BY bytes DESC;这里bytes是段占用的字节数除以 1024 两次就是 MB。segment_type常见有TABLE、INDEX、LOBSEGMENT、LOBINDEX等。如果只想看表的大小过滤segment_type TABLE即可。注意一个问题索引不包含在这个结果里。想同时看到表和索引的大小需要稍微改一下SELECT segment_name, SEGMENT_TYPE, ROUND(bytes / 1024 / 1024, 2) AS size_mb FROM user_segments WHERE segment_type IN (TABLE, INDEX, LOBSEGMENT) ORDER BY segment_name, segment_type;如果你有 DBA 权限想看所有用户的表用dba_segmentsSELECT owner, segment_name, segment_type, ROUND(bytes / 1024 / 1024, 2) AS size_mb FROM dba_segments WHERE segment_type TABLE ORDER BY bytes DESC;这里的owner就是用户/模式名。不同 Oracle 版本的视图字段基本兼容但高版本中字节数溢出需要用dba_extents按区聚合这种情况比较少见日常工作用bytes就够了。3.2 达梦、人大金仓等国产数据库的兼容写法国产数据库这两年出现频率很高最常被问到的是达梦和人大金仓。达梦 DM8 设计时兼容了 Oracle 的很多语法习惯所以查表大小可以直接先试 Oracle 的写法。达梦系统视图中同样有user_segments、dba_segments使用方式和 Oracle 高度相似。下面这个写法在达梦 8 上实测可用SELECT segment_name, segment_type, ROUND(bytes / 1024 / 1024, 2) AS size_mb FROM user_segments WHERE segment_type TABLE ORDER BY bytes DESC;如果你在达梦里查user_segments没有数据先确认当前登录用户是否有对象。用 DBA 账号登录就查dba_segments权限不足时也可以查all_segments。字段命名上达梦基本沿用了SEGMENT_NAME、SEGMENT_TYPE、BYTES兼容性比想象中好。人大金仓 KingbaseES 则是基于 PostgreSQL 内核查表大小直接用 PostgreSQL 的函数具体写法后面会有专门一节。很多企业在做 Oracle 到达梦或金仓的迁移时因为不了解这种元数据视角的差异迁移完才发现容量统计脚本全废了。同步工具能搬数据但搬不了“查看方式”。所以迁移项目里我一般建议提前把监控和统计脚本也纳入改造范围不然上线后查容量会无从下手。4. SQL Server 和 PostgreSQL两个“意见领袖”的解法4.1 SQL Serversp_spaceused 与 DMV 二选一SQL Server 最熟悉的查看方式应该是sp_spaceused这个存储过程EXEC sp_spaceused Nyour_table;它会返回几列信息rows行数、reserved保留空间、data数据占用、index_size索引占用、unused未使用空间。其中reserved是总空间data index_size unused加起来约等于reserved。单位是 KB不用再用 1024 换算两遍。但sp_spaceused一次只能看一张表想看整个库所有表的大小就不太方便了。这时候用 DMV动态管理视图写一条聚合 SQL 更高效SELECT t.name AS table_name, SUM(p.reserved_page_count) * 8 AS reserved_kb, SUM(p.used_page_count) * 8 AS used_kb, SUM( CASE WHEN p.index_id 2 THEN p.used_page_count ELSE 0 END ) * 8 AS data_kb, SUM( CASE WHEN p.index_id 2 THEN p.used_page_count ELSE 0 END ) * 8 AS index_kb FROM sys.dm_db_partition_stats p JOIN sys.tables t ON p.object_id t.object_id JOIN sys.schemas s ON t.schema_id s.schema_id GROUP BY t.name ORDER BY reserved_kb DESC;这里reserved_page_count是已分配页数乘以 8 是因为 SQL Server 每页 8KB。index_id 2表示堆或聚集索引的数据页index_id 2表示非聚集索引页。sys.dm_db_partition_stats是分区级别的加了聚合以后按表汇总正好覆盖分区表场景。需要注意sp_spaceused和 DMV 查出来的数字可能略有出入原因在于元数据缓存的刷新时机不同。正常情况下两者差异不大如果差异明显先执行DBCC UPDATEUSAGE刷新一下再查。4.2 PostgreSQLpg_total_relation_size 全家桶PostgreSQL 查看表大小应该是最方便的了因为官方直接提供了一族函数-- 表数据大小不含索引 SELECT pg_size_pretty(pg_table_size(schema_name.table_name)); -- 索引总大小 SELECT pg_size_pretty(pg_indexes_size(schema_name.table_name)); -- 表 索引 TOAST TOAST索引 的总大小 SELECT pg_size_pretty(pg_total_relation_size(schema_name.table_name));pg_size_pretty会自动把字节数转成 KB、MB、GB可读性很好。日常巡检我一般直接查pg_total_relation_size因为它把 TOAST 表也算进去了。所谓 TOAST可以理解为 PostgreSQL 用来存放超大字段值的“附带存储区”比如一列塞了几 MB 的文本数据不会全塞在主表里而是拆到 TOAST 表主表只留一个指针。所以不管字段多大用pg_total_relation_size才能反映真实占用。如果想一次看所有表的大小可以这样写SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname || . || tablename)) AS total_size FROM pg_tables WHERE schemaname NOT IN (pg_catalog, information_schema) ORDER BY pg_total_relation_size(schemaname || . || tablename) DESC;这里有个细节schemaname || . || tablename拼接出来的字符串是public.users这种格式如果表名是带大写或特殊字符的必须写成public.Users字符串拼接就会失效。稳妥的做法是直接用format()SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(format(%I.%I, schemaname, tablename))) AS total_size FROM pg_tables WHERE schemaname NOT IN (pg_catalog, information_schema) ORDER BY pg_total_relation_size(format(%I.%I, schemaname, tablename)) DESC;%I会按标识符格式处理自动加引号避免大小写问题。这个细节我踩过坑单独提一下。5. 图形化工具与面试题怎么快速“抄作业”5.1 用 Navicat、DBeaver 等工具直接看很多读者说命令行不熟能不能用工具看。当然可以。Navicat 里选中一个表右键选择“对象信息”或者看“表大小”它其实就是在底层调用了information_schema或对应数据库的系统视图包装成图形界面给你看。DBeaver 也有类似功能数据库导航树展开表后通常能看到“大小”相关字段。工具查起来方便但有两个问题第一工具显示的都是逻辑大小基于系统视图统计。如果统计信息没更新工具显示也一样滞后。我在 MySQL 上就遇到过 Navicat 显示表只有 1GB实际数据文件已经到了 5GB因为统计信息没刷新。第二版本不同入口不同不能指望读者照着截图操作。我建议图形化工具用来“快速定位异常”但做容量报表、趋势分析、迁移评估时还是写 SQL 脚本更靠谱可重复、可定时、可留痕。另外现在数据库同步场景越来越常见不管是用同步工具做实时复制还是做一次性的全量搬迁都要先摸清单张大表的体积。同步的并行度、断点续传阈值、临时磁盘空间全是按最大表来估算的。图形化工具一眼看一下没问题真要出数据还是得写查询脚本导成 CSV丢给同步方案里用。5.2 面试官问“如何查看表大小”到底想考什么这个话题在数据库面试题里出现频率不低。面试官的一句“你怎么查表大小”表面考命令实际考三个层次第一层知不知道数据字典在哪。MySQL 答information_schema.tablesOracle 答user_segmentsSQL Server 答sp_spaceused或 DMVPostgreSQL 答pg_total_relation_size这属于基本功。第二层懂不懂索引也算空间。只说“data_length”不算完整能主动补上index_length或者能说清“表大小 数据 索引”说明对存储结构有概念。第三层懂不懂统计口径和误差。能解释“视图查询结果是统计信息不代表实时物理文件大小”能提到 ANALYZE TABLE 或OPTIMIZE TABLE能说清高水位、碎片、TOAST 这些细节说明是真排过障的。如果面试问“给你一张 10 亿行的大表怎么快速评估它的体量”直接跑COUNT(*)是大忌。正确思路是先查统计信息拿个数量级再看data_length index_length估算容量需要精确值再考虑采样或者用元数据。这个认知会明显拉开和普通候选人的差距。6. 常见问题与排查技巧实录6.1 我实际踩过的坑坑一查出来是 NULL。MySQL 里information_schema.tables字段为 NULL最常见原因是权限不足。当前账号看得到表名但没权限读元数据统计。解决办法是给账号加上对应库的权限或者换一个有权限的账号查。还有一种情况是表名大小写问题Linux 上 MySQL 的表名是区分大小写的查询条件里的库名或表名大小写不对结果为空。坑二SQL Server 显示结果和盘上文件一直对不上。某次数据清理后sp_spaceused显示表占用 50GB实际备份文件明显小很多。原因是大量删除操作留下了碎片和未使用空间数据页没释放。这类问题要用索引重建或收缩来整理常见的做法是ALTER INDEX ALL ON your_table REBUILD;或者DBCC SHRINKDATABASE。收缩操作在高负载环境要慎用最好放维护窗口。坑三PostgreSQL 表名带大写字母字符串拼接报错。我在前面提过schemaname || . || tablename对驼峰命名的表会失败。报错信息一般是“关系不存在”。解决方法是尽量用format(%I.%I, schemaname, tablename)。这里把我自己的习惯再强调一次查询脚本里凡涉及动态拼接对象名一律走格式化函数不手动拼。坑四Oracle 表 DELETE 后空间一直不见小。因为表段的高水位标记不会自动下降DELETE 只是把行标记删除段大小不变。要让空间真正释放要么ALTER TABLE your_table SHRINK SPACE;要么ALTER TABLE your_table MOVE;再不行就走导出导入重建表。SHRINK SPACE要求表所在表空间开启行移动大表操作会锁表要挑业务低峰做。6.2 一张速查表帮你快速定位遇到一个新的数据库实例不知道从哪查起时直接看下面这张表数据库推荐查询方式注意点MySQLinformation_schema.tables统计信息可能滞后可用ANALYZE TABLE刷新独立表空间可看 .ibd 物理文件Oracleuser_segments/dba_segments索引是独立段要和表分开查DELETE 后段大小不会自动收缩SQL Serversp_spaceused或sys.dm_db_partition_stats页大小 8KB统计数据有缓存必要时先执行DBCC UPDATEUSAGEPostgreSQLpg_total_relation_size()TOAST 表会独立占用空间拼接表名要用format(%I.%I)达梦 DM8user_segments/dba_segments兼容 Oracle 语法字段命名基本一致人大金仓 KingbaseESpg_total_relation_size()基于 PostgreSQL 内核方法同 PG如果是要做迁移或同步我的习惯是先跑一遍大表 Top20输出成一个 CSV。里面包含库名、表名、数据大小、索引大小、估计行数、物理文件路径这几列。同步工具的参数、并行度、增量策略基本都能从这张表推导出来。容量规划也一样连续几周记录同一张清单增长速度趋势就有了就不用等磁盘告警了再手忙脚乱。这个主题放到屠龙刀法里是因为它在运维、迁移、面试三个场景都能用上。我个人现在每个月都会固定跑一遍各库的大表清单存下来跟上月对比。数据库出问题之前很多时候增长的苗头早就藏在数字里了。
RELATED

相关推荐

3个免费工具搞定wordpress富文本表单,让官网访客主动留资

3个免费工具搞定wordpress富文本表单,让官网访客主动留资

3个免费工具搞定wordpress富文本表单,让官网访客主动留资 网站做好了没人访问,比没做还让人焦虑。你盯着后台那惨淡的UV数据,心里直打鼓:是不是SEO没做好?还是内容太干瘪?其实,很多时候问题出在“交互”上。访客来了,看了一眼,觉得填…

📅 2026/9/16 2:52:04
ENVI中查看空间分辨率与重采样全攻略:从像元尺寸到算法选择

ENVI中查看空间分辨率与重采样全攻略:从像元尺寸到算法选择

我最早用ENVI的时候,最懵的一个点倒不是波段组合,也不是分类流程,而是拿到一景影像后压根不知道它是多少分辨率。别人问我“你手上这个是2米还是10米的”,我嘴上含糊应付,心里其实一片空白。后来才明白,分辨…

📅 2026/9/16 2:52:04
C# WPF半导体晶圆搬运上位机实战

C# WPF半导体晶圆搬运上位机实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/16 2:52:04
MORE NEWS

更多资讯

📰

声发射全波形采集:从参数摘要到原始信号取证的技术跃迁

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Claude Code 从零安装配置指南:终端里的AI编程协作者上手教程

前阵子和朋友聊到Claude Code,他说这东西到底好在哪,值不值得折腾一遍。我的回答很简单:如果你日常要写代码、改项目、处理一堆脚本任务,那它不是一个“又一个AI聊天窗口”,而是一个能直接住在你终端里的AI协作者。安装…

📰

C# async/await编译原理:状态机如何实现异步线性化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Word/WPS论文图片编号自动更新:题注与交叉引用实操指南

写论文最怕什么?我最怕的不是查重,是导师一句“第三章那张图删了重画”。一张图说删就删,后面十几张图的编号和正文里所有“如图X所示”全都要跟着改。手动改一遍,少说要半小时,改完还可能漏,最气人的是过了…

📰

DeepSeek V4.1 Flash部署实战:vLLM与SGLang选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

抓包工具实战指南:从Wireshark到科来,深入协议分析与网络排障

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬