字段类型选错、索引失效、大表未分区或归档是MySQL性能三大隐患:VARCHAR过长、TEXT/DATEIME滥用、枚举用字符串均拖慢查询;复合索引顺序错、函数操作、LIKE前缀通配导致索引失效;单表超2000万行须分区或归档。

字段类型选错会让查询变慢好几倍
MySQL 用 VARCHAR(255) 存手机号、用 TEXT 存短文本、用 DATETIME 存时间戳但实际只存日期——这些都会拖慢查询和索引效率。VARCHAR 长度远超实际需要,会导致排序/临时表使用更多内存;TEXT 类型无法直接建普通索引(除非加前缀);DATETIME 比 DATE 或 TINYINT 存状态多占 5 字节,还影响缓存命中率。
- 身份证号、手机号这类固定长度且无计算需求的,优先用
CHAR(比如CHAR(18)),比VARCHAR少存储长度开销 - 枚举类字段(如性别、订单状态)别用
VARCHAR或TEXT,改用TINYINT UNSIGNED+ 注释说明含义,节省空间且比较快 - 时间字段按精度选:只要日期就用
DATE,要时分秒才用DATETIME,高并发写入场景可考虑INT UNSIGNED存 Unix 时间戳(注意时区处理) -
JSON字段慎用:不能直接索引全文,查询需解析字符串,大 JSON 还会显著拖慢主键查找
没加索引 or 索引失效是性能崩盘最常见原因
EXPLAIN 显示 type=ALL 或 key=NULL,基本等于全表扫描。常见陷阱不是“没建索引”,而是“建了但用不上”。
- 复合索引顺序必须匹配查询条件最左前缀:比如有索引
INDEX(status, created_at),查WHERE created_at > '2024-01-01'不会走这个索引 - 对字段做函数操作会让索引失效:
WHERE DATE(created_at) = '2024-01-01'→ 改成WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02' -
LIKE以通配符开头(LIKE '%abc')无法用索引,能改成后缀匹配就尽量用LIKE 'abc%' -
OR条件两边字段没同时建索引,可能让整个条件退化为全表扫描;改用UNION或补全索引更稳
大表没做分区 or 归档,单表超千万行后维护成本飙升
单表 2000 万行以上,ALTER TABLE 可能锁表数小时,DELETE 历史数据也极慢,备份恢复时间不可控。
- 时间维度明显的表(如日志、订单)优先按月/年用
RANGE分区,例如:PARTITION BY RANGE (YEAR(created_at)) - 分区字段必须是主键或唯一索引的一部分,否则建表报错:
ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function - 别依赖分区自动清理数据;定期用
ALTER TABLE ... DROP PARTITION手动删旧分区,比DELETE WHERE快两个数量级 - 冷数据量大时,比分区更轻量的方案是归档到历史库+应用层路由,避免分区键设计僵化带来的后续改造成本
字段精度、索引有效性、数据生命周期——这三个地方一旦忽略,等流量上来再调,已经不只是慢的问题了。











