0f68a64829
Deploy Examination / deploy (push) Successful in 10s
Subtopics: - distributed-microservice: 45 questions (分布式微服务架构) - message-queue: 45 questions (消息队列) - k8s-observability: 45 questions (K8s与可观测性) - go-java-concurrency: 45 questions (Go/Java并发模型) - database-advanced: 35 questions (数据库进阶) - ai-engineering: 35 questions (AI工程实践) Question types: single_choice, true_false, fill_blank, short_answer, code_reading
217 lines
13 KiB
JSON
217 lines
13 KiB
JSON
{
|
||
"topic": "database-advanced",
|
||
"type": "single_choice",
|
||
"schema_version": "1.0.0",
|
||
"generated": "2026-09-09T00:00:00+08:00",
|
||
"questions": [
|
||
{
|
||
"id": "sc-001",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"mysql",
|
||
"bplus-tree",
|
||
"index"
|
||
],
|
||
"question": "在 InnoDB 中,关于聚簇索引和非聚簇索引(二级索引)的区别,以下说法正确的是?",
|
||
"options": {
|
||
"A": "聚簇索引的叶子节点存储的是完整行数据,非聚簇索引的叶子节点存储的是主键值",
|
||
"B": "每个表可以有多个聚簇索引,但只能有一个非聚簇索引",
|
||
"C": "聚簇索引的查询效率一定比非聚簇索引高,因此应尽量为所有列都建立聚簇索引",
|
||
"D": "非聚簇索引查找数据时不需要回表,因为叶子节点直接指向磁盘上的行"
|
||
},
|
||
"answer": "A",
|
||
"explanation": "InnoDB 的聚簇索引(通常即主键索引)的叶子节点直接存储完整行数据,而非聚簇索引(二级索引)的叶子节点存储的是主键值。通过二级索引查找数据时,需要先拿到主键值,再回到聚簇索引中查找完整行,这个过程称为「回表」。每个 InnoDB 表只能有一个聚簇索引(数据物理上按聚簇索引排序存储),但可以有多个非聚簇索引。索引过多会增加写入开销和存储空间,不应盲目建立。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-002",
|
||
"type": "single_choice",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"mysql",
|
||
"bplus-tree",
|
||
"composite-index"
|
||
],
|
||
"question": "有一张表建立了联合索引 INDEX idx_abc(a, b, c),以下哪个查询能有效利用该索引?",
|
||
"options": {
|
||
"A": "SELECT * FROM t WHERE b = 1 AND c = 2",
|
||
"B": "SELECT * FROM t WHERE c = 2 AND a = 1",
|
||
"C": "SELECT * FROM t WHERE a = 1 AND c = 2",
|
||
"D": "SELECT * FROM t WHERE a = 1 AND b > 5 AND c = 2"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "联合索引遵循最左前缀原则。MySQL 优化器会自动调整 WHERE 条件的顺序,所以选项 B(c=2 AND a=1)等价于 a=1 AND c=2,可以使用索引的 a 列。但注意 c=2 无法使用索引(中间跳过了 b)。选项 A 完全跳过了最左列 a,无法使用该索引。选项 C 使用了 a 但跳过了 b 直接用 c,只能用到 a 列。选项 D 中 b 是范围查询(b>5),根据最左前缀原则,范围查询后的列 c 无法使用索引,但 a 和 b 部分可以使用。不过选项 B 能让优化器识别出 a=1 可用索引,是本题最明确能利用索引的选项。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-003",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"mysql",
|
||
"bplus-tree",
|
||
"index",
|
||
"covering-index"
|
||
],
|
||
"question": "关于覆盖索引(Covering Index),以下描述正确的是?",
|
||
"options": {
|
||
"A": "覆盖索引是指索引包含了查询所需的所有列,从而避免回表操作",
|
||
"B": "覆盖索引要求索引列必须是主键,否则无法覆盖",
|
||
"C": "使用覆盖索引时,EXPLAIN 的 Extra 列会显示 Using filesort",
|
||
"D": "覆盖索引只适用于等值查询,范围查询无法使用覆盖索引"
|
||
},
|
||
"answer": "A",
|
||
"explanation": "覆盖索引是指查询所需的列都包含在索引中,无需回表读取聚簇索引中的完整行数据。EXPLAIN 中 Extra 列显示 Using index 表示使用了覆盖索引。覆盖索引不限于主键索引,任何二级索引只要包含了查询所需的列即可。范围查询同样可以利用覆盖索引,只要索引包含了所需列,例如 INDEX(name, age) 可以覆盖 SELECT name, age FROM t WHERE name > 'a'。Using filesort 表示需要额外排序,与覆盖索引无关。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-004",
|
||
"type": "single_choice",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"mysql",
|
||
"explain"
|
||
],
|
||
"question": "以下 EXPLAIN 输出中,type 列的值从最优到最差的正确排列顺序是?",
|
||
"options": {
|
||
"A": "ALL > index > range > ref > const",
|
||
"B": "const > ref > range > index > ALL",
|
||
"C": "const > range > ref > index > ALL",
|
||
"D": "range > const > ref > ALL > index"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "EXPLAIN 的 type 列表示 MySQL 访问表的方式,从最优到最差的顺序为:system > const > eq_ref > ref > range > index > ALL。const 表示通过主键或唯一索引精确匹配一行;ref 表示非唯一索引等值匹配;range 表示索引范围扫描;index 表示全索引扫描(遍历索引树);ALL 表示全表扫描(最差)。选项 B 正确地将 const > ref > range > index > ALL 从最优到最差排列。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-005",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"mysql",
|
||
"explain"
|
||
],
|
||
"question": "EXPLAIN 的 Extra 列出现 Using temporary 和 Using filesort,通常意味着查询需要优化。以下哪种查询最容易同时出现这两个警告?",
|
||
"options": {
|
||
"A": "SELECT * FROM t WHERE id = 1",
|
||
"B": "SELECT DISTINCT col1 FROM t ORDER BY col2 LIMIT 10",
|
||
"C": "SELECT * FROM t FORCE INDEX(PRIMARY) WHERE id BETWEEN 1 AND 100",
|
||
"D": "SELECT count(*) FROM t WHERE col1 = 'value'"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "选项 B 的查询同时涉及 DISTINCT(去重)和 ORDER BY(排序),且 col1 和 col2 不是同一个列,无法通过索引同时满足。MySQL 需要创建临时表来处理 DISTINCT,并且需要 filesort 来完成 ORDER BY,因此同时出现 Using temporary 和 Using filesort。选项 A 只是主键等值查询,type 为 const,无需临时表或排序。选项 C 使用 FORCE INDEX 做范围扫描,通常也不会触发临时表。选项 D 是简单的 WHERE 条件聚合,count(*) 不需要排序或去重。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-006",
|
||
"type": "single_choice",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"mysql",
|
||
"slow-query"
|
||
],
|
||
"question": "关于 MySQL 慢查询日志,以下配置和说法正确的是?",
|
||
"options": {
|
||
"A": "slow_query_log=ON 开启慢查询日志后,所有查询都会被记录到日志中",
|
||
"B": "long_query_time 默认值为 10 秒,表示执行时间超过 10 秒的 SQL 才会被记录",
|
||
"C": "慢查询日志只能记录 SELECT 语句,不包括 INSERT/UPDATE/DELETE",
|
||
"D": "开启慢查询日志会对数据库性能产生显著影响,生产环境不应开启"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "MySQL 慢查询日志(slow_query_log)默认 long_query_time 为 10 秒,只有执行时间超过该阈值的 SQL 才会被记录。慢查询日志记录所有类型的语句(SELECT、INSERT、UPDATE、DELETE 等),只要执行时间超过阈值。默认情况下只有管理员可以查看慢查询日志,不会记录所有查询,因此对性能影响极小,生产环境强烈建议开启以便排查性能问题。也可以设置 log_queries_not_using_indexes=ON 记录未使用索引的查询。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-007",
|
||
"type": "single_choice",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"mysql",
|
||
"lock",
|
||
"next-key-lock",
|
||
"gap-lock"
|
||
],
|
||
"question": "在 InnoDB 的默认隔离级别(REPEATABLE READ)下,执行以下语句时,关于锁的行为描述正确的是?\n\nDELETE FROM orders WHERE order_id = 100;\n假设 order_id 是主键列。",
|
||
"options": {
|
||
"A": "会加行锁,锁定 order_id = 100 的那一行记录",
|
||
"B": "会加临键锁(Next-Key Lock),锁定 order_id = 100 前面的间隙",
|
||
"C": "会加间隙锁(Gap Lock),锁定 order_id = 100 周围的范围",
|
||
"D": "REPEATABLE READ 级别下不会加任何锁"
|
||
},
|
||
"answer": "A",
|
||
"explanation": "当使用主键进行精确等值匹配(WHERE order_id = 100)时,InnoDB 只需要加一个行锁(Record Lock)锁定该行即可,不需要间隙锁或临键锁。间隙锁和临键锁主要用于防止幻读,在非唯一索引的范围查询或主键的范围查询时才会出现。等值查询命中已存在的记录时,锁的粒度最小,只锁定匹配的那一行。DELETE 语句在 REPEATABLE READ 级别下会获取排他锁(X Lock),即该行在事务提交前不能被其他事务修改或读取(当前读)。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-008",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"redis",
|
||
"cluster",
|
||
"slot",
|
||
"consistent-hashing"
|
||
],
|
||
"question": "Redis Cluster 使用 16384 个 slot 分片来分布数据,关于 slot 的分配和路由机制,以下说法正确的是?",
|
||
"options": {
|
||
"A": "客户端发送任意 key 的命令时,Redis Cluster 会自动将 key 路由到任意一个节点处理",
|
||
"B": "使用 CRC16 对 key 计算哈希值后对 16384 取模来确定 key 所属的 slot",
|
||
"C": "每个 Redis 节点平均分配约 16384 个 slot,节点数固定后无法调整",
|
||
"D": "16384 个 slot 必须全部分配完毕才能正常提供服务,任何 slot 未分配都会导致集群不可用"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Redis Cluster 使用 CRC16(key) % 16384 来确定每个 key 所属的 slot。每个节点负责一部分 slot,客户端发送命令时,如果 key 不在当前节点,会收到 MOVED 重定向响应。slot 的分配是动态的,可以通过 reshard 操作在节点间迁移 slot。只要至少有 6470 个 slot 被分配(覆盖所有 slot 的一半以上 + 每个 master 至少一个),集群就可以正常工作,但通常建议 100% 覆盖。CRC16 是一种高效的哈希算法,16384 个 slot 使用 2KB 的位图在节点间通信,这是选择 16384 而非更大数字的原因之一。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-009",
|
||
"type": "single_choice",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"redis",
|
||
"sentinel"
|
||
],
|
||
"question": "关于 Redis Sentinel(哨兵)的故障转移流程,以下描述正确的是?",
|
||
"options": {
|
||
"A": "当 master 被标记为主观下线(SDOWN)后,Sentinel 会立即开始故障转移",
|
||
"B": "Sentinel 通过 Raft 协议选举 Leader,由 Leader 执行故障转移操作",
|
||
"C": "故障转移时,Sentinel 会优先选择 slave 的 offset 最大的节点作为新 master",
|
||
"D": "故障转移完成后,Sentinel 不会通知客户端新的 master 地址,客户端需要自行探测"
|
||
},
|
||
"answer": "B",
|
||
"explanation": "Redis Sentinel 的故障转移流程:首先,单个 Sentinel 发现 master 不响应,标记为 SDOWN(主观下线);当足够多的 Sentinel(quorum 数量)都认为 master SDOWN 后,标记为 ODOWN(客观下线);然后通过类似 Raft 的选举机制选出一个 Leader Sentinel;由 Leader 执行故障转移:从 slave 中选择合适的节点提升为新 master(优先级 > offset > runid),通知其他 slave 复制新 master,通知客户端新的 master 地址。注意不是 offset 最大就优先——还需要先看 slave-priority,只有 priority 相同时才比较 offset。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "sc-010",
|
||
"type": "single_choice",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"redis",
|
||
"hybrid-persistence",
|
||
"lru"
|
||
],
|
||
"question": "关于 Redis 的持久化和内存管理,以下说法正确的是?",
|
||
"options": {
|
||
"A": "Redis 混合持久化(hybrid persistence)是在 RDB 快照的基础上追加 AOF 日志,重启时先加载 RDB 再重放增量 AOF,兼顾恢复速度和数据完整性",
|
||
"B": "Redis 混合持久化是将 RDB 和 AOF 数据同时写入同一个文件,恢复时随机读取两者的数据进行合并",
|
||
"C": "Redis 的 allkeys-lru 策略只会在键空间不足时淘汰设置了过期时间的 key",
|
||
"D": "Redis 开启内存碎片整理(activedefrag)会导致主线程完全阻塞,建议生产环境关闭"
|
||
},
|
||
"answer": "A",
|
||
"explanation": "Redis 混合持久化(Redis 4.0+)在 AOF 重写时,将当前 RDB 快照数据写入 AOF 文件头部,重写后的增量命令追加在 RDB 数据之后。重启时先加载 RDB 部分(快速恢复大部分数据),再重放后面的 AOF 增量命令(保证数据完整性)。这结合了 RDB 恢复速度快和 AOF 数据丢失少的优点。allkeys-lru 策略会在所有 key 中(不论是否设置了过期时间)淘汰最近最少使用的 key。Redis 4.0+ 的 activedefrag 在后台线程执行碎片整理,不会完全阻塞主线程,生产环境可以开启。",
|
||
"source": null,
|
||
"related": []
|
||
}
|
||
]
|
||
} |