主键应使用紧凑递增的自增BIGINT,避免UUID等随机值引发页分裂;复合索引按选择性、等值→范围→排序顺序排列;VARCHAR长度需合理设定;高频更新字段慎建索引。

为什么主键必须是紧凑且递增的
B+树性能高度依赖叶子节点的物理连续性和写入顺序。如果主键用 UUID 或 MD5 这类随机字符串,新记录会不断插入到B+树中间位置,引发大量页分裂(page split)和磁盘随机写,缓冲池命中率骤降。
实操建议:
- 优先使用自增
BIGINT作为主键,哪怕业务上不直接暴露;不要用VARCHAR(36)存 UUID 当主键 - 若必须用业务ID(如订单号),确保它本身具备时间递增性(如
20260903123456),并搭配UNSIGNED和足够位宽 - 避免在主键上做函数转换,例如
WHERE YEAR(create_time) = 2026会让主键索引完全失效
复合索引字段顺序怎么排才不白建
MySQL 的 B+树索引遵循最左前缀匹配原则,但“最左”不是语法顺序,而是数据分布与查询模式共同决定的——字段的选择性(cardinality)越高,越应靠左。
常见错误现象:
-
CREATE INDEX idx_status_user ON orders(status, user_id):status 只有 'pending'/'paid'/'done' 几个值,选择性极低,user_id 却是高区分度字段,这个索引对WHERE user_id = ?完全无效 -
WHERE user_id = 123 AND create_time > '2026-01-01'却建了(create_time, user_id),导致范围扫描后无法用 user_id 做等值过滤
实操建议:
- 先看
SELECT COUNT(DISTINCT col)/COUNT(*) FROM table,选择性 > 0.1 的字段更适合放左边 - 等值查询字段(
=、IN)放最左,范围查询字段(>、BETWEEN)放右边,排序字段(ORDER BY)可接在范围字段之后(MySQL 8.0 支持降序索引) - 用
EXPLAIN FORMAT=JSON查看used_key_parts,确认实际用了索引的哪几段
TEXT/VARCHAR 长度设太大真会拖慢B+树
B+树非叶子节点只存索引键值,但如果字段定义过长(比如 VARCHAR(2000)),即使实际只存 10 字符,InnoDB 在构建索引时仍可能按最大长度预留空间,导致单页容纳键值数量下降,树变高,I/O 次数增加。
实操建议:
- 用
VARCHAR时按真实业务上限设长度,别无脑VARCHAR(255)或VARCHAR(1024) - 超过 255 字节的字段(如长文本、JSON 内容)不要参与索引;需要检索其中部分内容,改用
GENERATED COLUMN + STORED提取关键字段再建索引 - 对邮箱、手机号这类固定格式字段,优先用
VARCHAR(64)或VARCHAR(32),而非TEXT
什么时候该禁用索引而不是优化它
索引不是越多越好。每个额外索引都会增加 INSERT/UPDATE/DELETE 的维护成本,并占用 Buffer Pool 空间。当一张表写多读少、或某个字段更新极其频繁时,索引可能成为瓶颈本身。
实操建议:
- 检查
sys.schema_unused_indexes视图,定期清理长期未被使用的索引 - 对高频更新的状态字段(如
is_deleted TINYINT、retry_count INT),除非有明确的WHERE is_deleted = 0查询需求,否则不要单独建索引 - 用
ALTER TABLE t ADD INDEX idx_xxx (col) INVISIBLE先设为不可见,观察慢查日志和performance_schema.table_io_waits_summary_by_index_usage,再决定是否启用
B+树的性能天花板不在参数调优,而在 Schema 设计的第一笔 DDL —— 字段类型、主键形态、索引字段组合,这些决策一旦固化,后期调整成本远高于加内存或换磁盘。



















