← 每日面试题 学习看板

一个表有用户和时间两个列,现有3个需求:根据用户查;根据日期查;根据日期和用户查;问怎么建立索引?

面试题/01实践场景题/实践场景题目/数据库与存储/一个表有用户和时间两个列,现有3个需求:根据用户查;根据日期查;根据日期和用户查;问怎么建立索引?.md

面试记录 2026-10-21

题目:一个表有用户和时间两个列,现有3个需求:根据用户查;根据日期查;根据日期和用户查;问怎么建立索引?

难度:medium

标签:mysql/index

评分:⭐⭐⭐⭐☆(4/5)

我的回答

创建一个联合索引加一个单独索引。联合索引使用用户 ID 在前、时间在后,再单独建立一个时间索引。因为只有联合索引不能覆盖全部情况,建两个单独索引又无法优化日期和用户同时查询,所以选择一个联合索引加一个单列索引,单列索引选时间,因为时间区分度较好,表数据量大时还可以做分区表。

点评

优点:(user_id, date) + date 的组合完全正确,并想到区分度与分区。

不足:没说透「为什么等值列在前、范围列在后」,也没提索引数量带来的写放大。

补充:最左前缀决定 (user, date) 能服务「按用户」和「用户+日期范围」;(date, user) 则服务不了只按用户查。用 EXPLAIN 验证,按实际查询频次决定是否值得多一个索引。

完整讲解

第一部分:知识重点剖析

这是最左前缀的经典题。三个查询分别是:where user_id=?、where date between ?、where user_id=? and date between ?。(user_id, date) 覆盖后两者(等值 + 范围),date 单列覆盖纯日期查询。索引设计的判断依据是「等值列在前、范围列在后」,再加上查询频次与写入成本的权衡。

第二部分:考察方向与延伸递进

  1. 如果查询是 date=? and user_id=? 呢?——等值顺序无关,优化器会重排。
  2. 能不能只建 (user_id, date) 不建 date?——纯日期查询会全表扫,取决于该查询频次。
  3. 区分度低的时间列单独建索引有意义吗?——按天范围查有意义,按单点查可能不如全表。

第三部分:面试者参考回答

【一句话结论】 建一个 (user_id, date) 联合索引加一个 date 单列索引,分别覆盖组合查询和纯日期查询。

【三点展开】 第一,联合索引把等值的 user_id 放前面、范围的 date 放后面,这样按用户查和用户加日期查都能走。第二,纯日期查询用不上联合索引的最左列,所以要单独建 date 索引。第三,索引不是越多越好,多一个索引就多一份写入和存储成本,要按查询频次取舍。

【一句边界】 如果日期查询只查最近几天,可以用分区裁剪替代单列索引;如果写入压力极大,宁可让低频查询走从库。