← 返回面试专题导航

📑 表结构与索引设计面试题

字段类型、主键策略与索引设计直接决定系统上限

📚 表结构建模与索引实践

1. 设计表结构时,字段类型选择有哪些原则?简单
  • 能用整数就不用字符串,如状态、类型等。
  • 长度尽量精确,避免 VARCHAR(255) 滥用。
  • 金额使用 DECIMAL,避免浮点精度问题。
  • 时间统一使用 DATETIME / TIMESTAMP 或 bigint 毫秒数。
2. 如何选择合适的主键?自增 ID 和业务 ID 各有什么优缺点?简单
  • 自增 ID:简单、连续,聚簇索引顺序写,性能好;缺点是容易被枚举、跨库时需要额外全局 ID。
  • 业务 ID(如订单号):可以编码业务含义,不暴露真实数量;但作为主键可能比较长。
  • 常见做法:内部使用自增主键,业务使用单独的业务编号字段并建立唯一索引。
3. 唯一键(UNIQUE)和普通索引在设计上有什么不同?什么时候需要唯一键?中等
  • 唯一键在逻辑上约束列值不重复,MySQL 层会做唯一性校验。
  • 普通索引只提供加速,不保证唯一性。
  • 账号、邮箱、手机号、第三方 ID 等天然唯一的字段应使用唯一键,防止脏数据。
4. 如何为一个典型的订单表设计索引?请给出示例。中等
CREATE TABLE `order`(
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  order_no VARCHAR(32) NOT NULL,
  user_id BIGINT NOT NULL,
  status TINYINT NOT NULL,
  pay_time DATETIME,
  created_at DATETIME NOT NULL,
  INDEX idx_user_created (user_id, created_at),
  INDEX idx_status_created (status, created_at),
  UNIQUE uk_order_no (order_no)
);

结合实际查询场景(按用户分页、按状态筛选)设计联合索引。

5. 什么时候应该使用联合索引而不是多个单列索引?中等
  • 查询条件经常同时包含多个列,如 WHERE user_id = ? AND status = ?
  • 需要利用索引顺序进行排序或范围查询。
  • MySQL 一般只会选择一个最优索引,多列条件下联合索引更高效。
6. 如何避免把 NULL 设计进索引列?NULL 对索引有什么影响?中等
  • NULL 值会让索引统计信息变复杂,某些情况下优化器估算不准确。
  • 联合索引中出现可为 NULL 的列时,可能影响最左前缀使用。
  • 实践中建议:能 NOT NULL 就 NOT NULL,并设置业务上合理的默认值。
7. 如何为状态字段设计更可扩展的结构?是单列 int 还是多列 boolean?中等
  • 多数情况下使用单列整型并配合枚举表或代码枚举,便于索引与扩展。
  • 布尔字段较多时可考虑 bit 位或 JSON 扩展,但要注意查询复杂度。
8. 设计历史表/归档表时,你会怎么做?与线上表有什么区别?中等
  • 字段结构基本一致,去掉不再需要的约束或索引。
  • 更多关注写入批量与查询归档范围(按时间分表/分区)。
  • 可以适当增加归档时间、操作人等元信息字段。
9. 大表拆分时,如何设计新旧表结构以便平滑迁移?中等
  • 新旧表保持主键与关键业务字段一致,便于双写和回放。
  • 通过中间层映射或视图兼容旧逻辑。
  • 拆分时避免一次性切换,采用灰度迁移。
10. 设计联合索引时,如何确定列的先后顺序?中等
  • 优先放选择性高的列,提高过滤效率。
  • 考虑最常见的查询 WHERE 和 ORDER BY 组合。
  • 避免把变化非常频繁的列放在前面,以减少页分裂。
11. 表设计时什么时候需要拆子表(如用户主表 + 扩展表)?中等
  • 主表字段过多,导致一行记录过大,影响缓存与 I/O。
  • 部分字段访问频率极低,可拆到扩展表节省缓存与带宽。
  • 不同字段生命周期差异大,如临时属性 vs 长期属性。
12. 哪些字段不建议建立索引?为什么?中等
  • 低选择性字段,如性别、布尔状态。
  • 频繁更新的字段,会增加维护成本。
  • 特别长的字符串字段,会导致索引体积巨大。
13. 设计日志/审计表时,索引应该怎么建?中等
  • 常用查询维度如用户、时间范围、操作类型上建索引。
  • 避免为低频查询建过多索引,写放大严重。
  • 结合分区和归档减少单表数据量。
14. 请讲一个你在项目中“重新设计表结构 + 索引”带来性能提升的案例。困难

按照“问题 → 分析 → 方案 → 效果”的结构讲述,例如:

  • 订单列表接口慢,发现大量 JOIN + 无索引过滤。
  • 重新设计订单表,增加联合索引和冗余字段,减少 JOIN。
  • 接口 p99 从 2s 降到 100ms,以此展示你的设计能力。
15. 总结一下你在“表结构与索引设计”方面的原则清单。中等
  • 以查询场景为中心设计表与索引。
  • 字段类型精确,避免浪费与隐式转换。
  • 联合索引优先覆盖高频查询和排序需求。
  • 适度冗余减少复杂 JOIN。