用char(11)存纯11位手机号比varchar更高效,因定长利于索引对齐;状态值优先选tinyint而非enum以避免序号偏移风险;全时区统一场景用datetime优于timestamp;text字段应拆分避免select *触发溢出页i/o。

用 VARCHAR 存手机号,查得慢?先看实际存储长度
多数人默认用 VARCHAR(20) 存手机号,但 MySQL 中 VARCHAR 的比较和索引查找效率,会受实际存入内容长度影响——尤其是当字段被用于 WHERE 或 JOIN 时。
如果所有手机号都是 11 位纯数字(如 '13812345678'),用 CHAR(11) 反而更稳:定长字段在 B+ 树索引中对齐更好,排序和范围扫描更少跳转。
- MySQL 8.0+ 对短
VARCHAR(≤ 255 字节)的行内存储已优化,但CHAR在utf8mb4下仍固定占 44 字节(11×4),而VARCHAR多 1–2 字节长度头 - 若字段含空格、括号或国际前缀(如
'+86-138-1234-5678'),VARCHAR更合理,但需在应用层清洗后写入,避免查询时用TRIM()或REPLACE()——这些函数会让索引失效 - 别在
VARCHAR字段上建前缀索引(如INDEX(phone(6)))来“省空间”,11 位手机号前 6 位高度重复(如全是138、159),索引区分度极低,等效于全表扫
TINYINT 和 ENUM 存状态值,哪个更快?
TINYINT 查询性能略优,但前提是状态值真的只有几个且稳定;ENUM 表面省空间,实际在排序、GROUP BY 和主从同步中容易出隐性问题。
比如定义 status ENUM('pending','paid','shipped','cancelled'),MySQL 内部按序号(1–4)存储,但一旦 ALTER TABLE 新增值(如中间插 'refunded'),原有数据的序号会整体偏移,导致主从不一致或 ORDER BY 结果错乱。
- 用
TINYINT UNSIGNED+ 注释说明映射(如// 1=pending, 2=paid...),应用层转换,数据库只管数值比较——索引查找快,无隐式转换开销 - 如果状态值未来可能扩展到 10+ 种,直接上
SMALLINT,别硬撑TINYINT,溢出后加字段代价远高于预留 1 字节 - 别把
ENUM当约束用:它不阻止插入非法字符串(MySQL 5.7+ 默认警告而非报错),真要强校验,用CHECK约束(MySQL 8.0.16+)或应用层控制
DATETIME vs TIMESTAMP:时区和范围怎么选不拖慢查询?
二者底层存储不同:TIMESTAMP 存 UTC 时间戳(4 字节),DATETIME 存字面值(5–8 字节),但真正影响性能的是时区转换逻辑。
1、对ASP内核代码进行DLL封装,从而大大提高了用户的访问速度和安全性;2、采用后台生成HTML网页的格式,使程序访问速度得到进一步的提升;3、用户可发展下级会员并在下级购买商品时获得差额利润;4、全新模板选择功能;5、后台增加磁盘绑定功能;6、后台增加库存查询功能;7、后台增加财务统计功能;8、后台面值类型批量设定;9、后台财务曲线报表显示;10、完善订单功能;11、对所有传输的字符串进行安全
如果业务全在中国时区(Asia/Shanghai),又频繁做 WHERE created_at > '2024-01-01',用 TIMESTAMP 反而多一层时区转换——MySQL 每次比较都要把输入字符串转为 UTC,再跟磁盘里存的 UTC 值比;而 DATETIME 是直存直比。
- 跨时区服务(如订单中心支持全球下单)才用
TIMESTAMP,否则统一用DATETIME,避免隐式转换打乱执行计划 -
TIMESTAMP范围只到 2038 年,如果存历史档案或长期合约时间,必须用DATETIME,否则 INSERT 会静默截断或报错 - 别在
TIMESTAMP字段上用CONVERT_TZ()做查询条件,函数包裹字段 = 索引失效;需要本地时区展示,应该在应用层转,不是 SQL 层转
大文本字段(TEXT/MEDIUMTEXT)为什么让 SELECT * 变慢?
不是因为它们“大”,而是因为 MySQL 默认把 TEXT 类型存在单独的溢出页(off-page),主记录只留 20 字节指针。只要 SELECT 涉及该字段,就要额外 I/O 去读那些页——哪怕你只取 1 行,哪怕字段值只有 100 字节。
更糟的是,如果表里有多个 TEXT 字段,或者用了 ROW_FORMAT=COMPACT(默认),小值也可能被挤出去,触发无谓的溢出读取。
- 把非必查的大字段(如日志原文、HTML 内容)拆到独立关联表,主表只留 ID,用 JOIN 按需加载
- 确认是否真需要
MEDIUMTEXT:如果最长内容不超过 64KB,TEXT就够,MEDIUMTEXT不提升性能,只增加管理复杂度 - 用
SELECT id, title FROM posts代替SELECT *,尤其当表含TEXT时,能直接避开溢出页读取
类型选错不会立刻报错,但会在慢查询、锁等待、复制延迟里慢慢咬你一口。最常被忽略的,是字段语义和实际数据分布之间的断层——比如用字符串存金额、用浮点存精度要求高的计数,这种错,索引和缓存都救不回来。










