网络宝典
第二套高阶模板 · 更大气的阅读体验

索引占用空间大吗?别被“看不见”的数据拖慢了数据库

发布时间:2026-04-02 10:30:47 阅读:4 次

你有没有遇到过这样的情况:表里就几十万条记录,但磁盘空间却悄悄涨到了几个G?查来查去,发现最大的“嫌疑对象”不是数据本身,而是——索引

索引真会吃空间?

会,而且有时候吃得还挺多。比如 MySQL 的 InnoDB 引擎,主键索引(聚簇索引)直接把整行数据存进 B+ 树叶子节点;而普通二级索引,叶子节点只存主键值,但非叶子节点也要存索引列+指针。一个 VARCHAR(200) 的字段建了索引,每条记录的索引项可能就要占上百字节——100 万条记录,光这一个索引就轻松干掉 100MB 以上。

举个实在的例子

假设有一张用户表:

CREATE TABLE users (
id BIGINT PRIMARY KEY,
phone VARCHAR(20),
email VARCHAR(100),
created_at DATETIME
);
再加两个索引:
ALTER TABLE users ADD INDEX idx_phone (phone);
ALTER TABLE users ADD INDEX idx_email (email);
手机字段平均长度 11 字节,邮箱平均 45 字节,加上指针、页头、B+ 树层级开销……实测下来,这两个索引加起来可能比原始数据还大 30%~50%。

哪些索引特别“占地”?

长文本字段(如 TEXT 前缀索引没设好)、JSON 字段全量索引、联合索引列太多(比如 (status, type, category, updated_at))、重复率极高的字段(如性别、状态枚举),都容易造成空间浪费。更麻烦的是,删除数据不等于释放索引空间——InnoDB 不会自动收缩索引页,得靠 OPTIMIZE TABLE 或重建表。

怎么知道它到底占了多少?

MySQL 里可以直接查:

SELECT
table_name,
round(((data_length + index_length) / 1024 / 1024), 2) AS total_mb,
round((index_length / 1024 / 1024), 2) AS index_mb
FROM information_schema.TABLES
WHERE table_schema = 'your_db' AND table_name = 'users';
看看 index_mb 占比,超过 40%,就得掂量掂量索引是不是建得太“豪横”了。

索引不是越多越好,也不是越全越稳。就像家里储物柜——放几件常用衣服没问题,可要是连去年的快递单都塑封归档,柜子早满了,找东西反而更费劲。