你有没有遇到过这样的情况:表里就几十万条记录,但磁盘空间却悄悄涨到了几个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%,就得掂量掂量索引是不是建得太“豪横”了。索引不是越多越好,也不是越全越稳。就像家里储物柜——放几件常用衣服没问题,可要是连去年的快递单都塑封归档,柜子早满了,找东西反而更费劲。