在 MySQL 中,查询表占用空间的核心是通过 information_schema.TABLES 系统表(存储数据库元数据),结合数据大小、索引大小、碎片空间等字段计算得出。以下是 不同场景的实用查询语句,包含单表、所有表、按大小排序等需求,同时说明字段含义和注意事项。

一、核心字段说明(information_schema.TABLES)

先明确关键字段的含义(单位:字节),后续查询会基于这些字段计算:

字段名含义
DATA_LENGTH表数据占用的空间(InnoDB 中含聚簇索引,MyISAM 中仅纯数据)
INDEX_LENGTH表索引占用的空间
DATA_FREE表碎片 / 未使用空间(InnoDB 中可能包含表空间剩余空间,MyISAM 为未分配空间)
TABLE_SCHEMA数据库名
TABLE_NAME表名

二、常用查询场景

1. 查询「单个表」的占用空间(推荐)

适用于精准查看某张表的总空间、数据空间、索引空间、碎片空间,结果转换为 MB 更直观:

sql

SELECT
  TABLE_SCHEMA AS '数据库名',
  TABLE_NAME AS '表名',
  -- 数据大小(MB)
  ROUND(DATA_LENGTH / 1024 / 1024, 2) AS '数据大小(MB)',
  -- 索引大小(MB)
  ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS '索引大小(MB)',
  -- 碎片空间(MB)
  ROUND(DATA_FREE / 1024 / 1024, 2) AS '碎片空间(MB)',
  -- 总占用空间(数据+索引+碎片,MB)
  ROUND((DATA_LENGTH + INDEX_LENGTH + DATA_FREE) / 1024 / 1024, 2) AS '总占用空间(MB)'
FROM
  information_schema.TABLES
WHERE
  TABLE_SCHEMA = '你的数据库名'  -- 替换为实际数据库名(如 test_db)
  AND TABLE_NAME = '你的表名';  -- 替换为实际表名(如 user_info)
2. 查询「某个数据库下所有表」的占用空间(按总大小排序)

适用于统计数据库内所有表的空间分布,快速定位大表:

sql

SELECT
  TABLE_SCHEMA AS '数据库名',
  TABLE_NAME AS '表名',
  ROUND(DATA_LENGTH / 1024 / 1024, 2) AS '数据大小(MB)',
  ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS '索引大小(MB)',
  ROUND(DATA_FREE / 1024 / 1024, 2) AS '碎片空间(MB)',
  ROUND((DATA_LENGTH + INDEX_LENGTH + DATA_FREE) / 1024 / 1024, 2) AS '总占用空间(MB)'
FROM
  information_schema.TABLES
WHERE
  TABLE_SCHEMA = '你的数据库名'  -- 替换为实际数据库名
ORDER BY
  (DATA_LENGTH + INDEX_LENGTH + DATA_FREE) DESC;  -- 按总空间倒序(大表在前)
3. 查询「所有数据库」的表空间总和(按数据库分组)

适用于对比多个数据库的总占用空间:

sql

SELECT
  TABLE_SCHEMA AS '数据库名',
  -- 该数据库所有表的数据总大小
  ROUND(SUM(DATA_LENGTH) / 1024 / 1024, 2) AS '总数据大小(MB)',
  -- 该数据库所有表的索引总大小
  ROUND(SUM(INDEX_LENGTH) / 1024 / 1024, 2) AS '总索引大小(MB)',
  -- 该数据库所有表的总占用空间
  ROUND(SUM(DATA_LENGTH + INDEX_LENGTH + DATA_FREE) / 1024 / 1024, 2) AS '数据库总占用空间(MB)'
FROM
  information_schema.TABLES
GROUP BY
  TABLE_SCHEMA
ORDER BY
  SUM(DATA_LENGTH + INDEX_LENGTH + DATA_FREE) DESC;

三、关键注意事项

  1. 单位转换:

    • 字节(B)→ 千字节(KB):除以 1024
    • 千字节(KB)→ 兆字节(MB):再除以 1024(合计 / 1024²)
    • 兆字节(MB)→ 吉字节(GB):再除以 1024(合计 / 1024³)示例:转换为 GB 只需把 1024 / 1024 改为 1024 / 1024 / 1024。
  2. 存储引擎差异:

    • InnoDB:DATA_LENGTH 包含聚簇索引(主键索引)的空间,DATA_FREE 可能包含表空间碎片或未分配的共享表空间(如使用 innodb_file_per_table=OFF 时,共享表空间的剩余空间会被统计)。
    • MyISAM:DATA_LENGTH 仅为数据文件(.MYD)大小,INDEX_LENGTH 为索引文件(.MYI)大小,DATA_FREE 为未使用的预留空间。
  3. 权限要求:查询 information_schema.TABLES 需要 SELECT 权限,普通用户通常可访问(若被限制,需联系管理员授权)。

  4. 碎片空间处理:若 DATA_FREE 过大(如超过数据大小的 50%),可通过 OPTIMIZE TABLE 表名;(MyISAM)或 ALTER TABLE 表名 ENGINE=InnoDB;(InnoDB)整理碎片(注意:整理时会锁表,需避开业务高峰)。

四、快速验证(示例)

假设查询数据库 test_db 中表 order_list 的空间:

sql

SELECT
  TABLE_SCHEMA,
  TABLE_NAME,
  ROUND(DATA_LENGTH/1024/1024,2) AS 数据大小MB,
  ROUND(INDEX_LENGTH/1024/1024,2) AS 索引大小MB,
  ROUND((DATA_LENGTH+INDEX_LENGTH)/1024/1024,2) AS 总大小MB
FROM information_schema.TABLES
WHERE TABLE_SCHEMA='test_db' AND TABLE_NAME='order_list';

返回结果示例:

TABLE_SCHEMATABLE_NAME数据大小 MB索引大小 MB总大小 MB
test_dborder_list28.5612.3440.90

更多推荐