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
216 lines
12 KiB
JSON
216 lines
12 KiB
JSON
{
|
||
"topic": "database-advanced",
|
||
"type": "fill_blank",
|
||
"schema_version": "1.0.0",
|
||
"generated": "2026-09-09T00:00:00+08:00",
|
||
"questions": [
|
||
{
|
||
"id": "fb-001",
|
||
"type": "fill_blank",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"mysql",
|
||
"bplus-tree",
|
||
"index"
|
||
],
|
||
"question": "在 InnoDB 中,主键索引的叶子节点直接存储______,因此基于主键查询效率最高;而二级索引的叶子节点存储的是主键值,查到后通常还需要______才能获取完整行数据。",
|
||
"answer": [
|
||
"完整行数据",
|
||
"整行数据",
|
||
"完整的行数据",
|
||
"聚簇索引回表",
|
||
"回表"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "InnoDB 使用聚簇索引(Clustered Index),主键索引的 B+ 树叶子节点存储的是完整的行数据,因此通过主键查询可以直接获取数据,无需额外的 IO。而二级索引(非聚簇索引)的叶子节点只存储主键值,查到主键后需要拿着主键回到聚簇索引中查找完整行数据,这个过程称为「回表」。回表会产生额外的随机 IO,是影响查询性能的重要因素。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-002",
|
||
"type": "fill_blank",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"mysql",
|
||
"index",
|
||
"composite-index"
|
||
],
|
||
"question": "联合索引 (a, b, c) 遵循最左前缀原则,以下查询中能使用该索引的有:WHERE a=1 AND b=2、WHERE a=1 AND c=3、WHERE b=2 AND c=3、WHERE a=1 ORDER BY b。其中 ______ 的查询无法使用索引(填查询条件序号,如 2、3)。",
|
||
"answer": [
|
||
"2、3",
|
||
"2和3",
|
||
"b=2 AND c=3, a=1 AND c=3",
|
||
"第2个和第3个",
|
||
"WHERE a=1 AND c=3, WHERE b=2 AND c=3"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "最左前缀原则要求查询条件从联合索引的最左列开始连续匹配。索引 (a, b, c):① WHERE a=1 AND b=2 命中前两列,可使用索引;② WHERE a=1 AND c=3 跳过了 b,只能用到 a 这一列,c 无法使用索引过滤;③ WHERE b=2 AND c=3 完全跳过了最左列 a,无法使用索引;④ WHERE a=1 ORDER BY b 命中 a 列,排序字段 b 在索引中紧跟 a,可避免 filesort。因此第 2、3 个查询无法有效利用索引。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-003",
|
||
"type": "fill_blank",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"mysql",
|
||
"index",
|
||
"covering-index"
|
||
],
|
||
"question": "当查询所需的所有列都包含在索引中时,MySQL 可以直接从索引获取数据而无需回表,这种技术称为______。在 EXPLAIN 的 Extra 列中会显示为 ______。",
|
||
"answer": [
|
||
"覆盖索引",
|
||
"Using index"
|
||
],
|
||
"answer_rule": "all",
|
||
"explanation": "覆盖索引(Covering Index)是指查询需要的所有字段都被某个索引所覆盖,InnoDB 只需扫描索引即可完成查询,避免了回表操作。此时 EXPLAIN 的 Extra 列会显示「Using index」,表示使用了覆盖索引。覆盖索引是优化查询性能的重要手段,能显著减少随机 IO。例如对索引 (name, age) 执行 SELECT name, age FROM users WHERE name = 'Tom',所有需要的列都在索引中,无需回表。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-004",
|
||
"type": "fill_blank",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"mysql",
|
||
"index",
|
||
"bplus-tree"
|
||
],
|
||
"question": "MySQL 5.6 引入的索引下推(Index Condition Pushdown,ICP)优化,将 ______ 下推到存储引擎层在索引扫描阶段完成过滤。在 EXPLAIN 的 Extra 列中,启用 ICP 时会显示 ______。",
|
||
"answer": [
|
||
"WHERE 条件过滤",
|
||
"部分 WHERE 条件",
|
||
"索引不覆盖的过滤条件",
|
||
"Using index condition"
|
||
],
|
||
"answer_rule": "all",
|
||
"explanation": "索引下推(ICP)是 MySQL 5.6 引入的优化。在没有 ICP 之前,存储引擎根据索引找到记录后回表,Server 层再进行 WHERE 过滤。ICP 将部分 WHERE 条件下推到存储引擎层,在索引扫描时就进行过滤,减少了回表次数和 Server 层的处理开销。当 ICP 生效时,EXPLAIN Extra 列显示「Using index condition」。注意 ICP 仅适用于 InnoDB 和 MyISAM,且只对联合索引起作用——因为单列索引的叶子节点已经包含了完整信息,不需要额外过滤。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-005",
|
||
"type": "fill_blank",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"mysql",
|
||
"explain"
|
||
],
|
||
"question": "EXPLAIN 执行计划的 type 列中,性能从好到差的大致顺序为:system > ______ > eq_ref > ref > range > index > ALL。其中 ______ 表示全表扫描,通常需要重点优化。",
|
||
"answer": [
|
||
"const",
|
||
"ALL"
|
||
],
|
||
"answer_rule": "all",
|
||
"explanation": "EXPLAIN 的 type 列表示 MySQL 在表中找到匹配行的方式。const 表示通过主键或唯一索引查找到单行(如 WHERE id=1),速度最快;eq_ref 表示对每一行的 JOIN 都从表中用主键/唯一索引查一行;ref 表示使用普通索引查找;range 表示索引范围扫描;index 表示全索引扫描;ALL 是全表扫描,性能最差。type 列是从左到右性能递减的,日常优化目标至少是 range 级别,避免 ALL。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-006",
|
||
"type": "fill_blank",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"mysql",
|
||
"slow-query",
|
||
"explain"
|
||
],
|
||
"question": "慢查询日志通过设置 ______ 参数(单位秒)开启,超过该阈值的查询会被记录。在 EXPLAIN 的 Extra 列中,______ 表示 MySQL 需要额外的排序操作,______ 表示使用了临时表,二者都可能消耗较多内存和 CPU,需要重点关注优化。",
|
||
"answer": [
|
||
"slow_query_log",
|
||
"long_query_time",
|
||
"Using filesort",
|
||
"Using temporary"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "慢查询日志通过 slow_query_log=ON 开启,long_query_time 设置阈值(默认 10 秒)。建议生产环境设为 1 秒甚至更低。EXPLAIN Extra 中:「Using filesort」表示 MySQL 无法利用索引完成排序,需要额外的排序算法(通常因为 ORDER BY 字段不在索引中);「Using temporary」表示使用了临时表(常见于 GROUP BY、DISTINCT、子查询等场景)。这两者通常意味着较大的内存和 CPU 开销,尤其在数据量大时性能影响显著,应通过优化索引和 SQL 来避免。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-007",
|
||
"type": "fill_blank",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"mysql",
|
||
"lock"
|
||
],
|
||
"question": "InnoDB 中,行锁基于索引实现,锁住的是索引记录而非物理行。当查询未命中索引时,InnoDB 会退化为______锁,锁定所有行,严重影响并发。间隙锁(Gap Lock)锁定的是索引记录之间的间隙,用于防止______插入,从而解决幻读问题。",
|
||
"answer": [
|
||
"表锁",
|
||
"幻读",
|
||
"新行",
|
||
"其他事务的"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "InnoDB 的行锁是通过给索引上的索引项加锁来实现的。如果 WHERE 条件没有走索引(如全表扫描),InnoDB 将锁住整个表(所有行),等效于表锁,严重降低并发性能。间隙锁(Gap Lock)锁住的是索引记录之间的「间隙」,以及第一条记录之前和最后一条记录之后的间隙,其目的是防止其他事务在间隙中插入新记录,从而避免幻读(Phantom Read)。临键锁(Next-Key Lock)= 行锁 + 间隙锁,是 InnoDB 在可重复读隔离级别下的默认锁类型。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-008",
|
||
"type": "fill_blank",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"redis",
|
||
"cluster",
|
||
"slot"
|
||
],
|
||
"question": "Redis Cluster 使用一致性哈希将数据分布在 16384 个 slot 中,每个 key 通过 CRC16 算法对 16384 取模确定所属 slot。当需要迁移 slot 时,使用 ______ 命令将 key-value 从源节点转移到目标节点,迁移过程中需要同时保持源和目标节点对该 slot 的访问。",
|
||
"answer": [
|
||
"MIGRATE",
|
||
"migrate"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "Redis Cluster 采用 16384 个虚拟节点(slot)来分配数据。每个 key 通过 CRC16(key) % 16384 确定 slot 编号,每个 master 节点负责一部分 slot。MIGRATE 命令用于在节点间迁移 key,它是一个原子操作:先在目标节点还原 key,成功后在源节点删除。迁移过程中,Redis Cluster 会通过 ASK/MOVED 重定向来保证客户端能正确路由请求。Redis Cluster 没有使用虚拟节点的概念,而是用固定的 16384 个 slot 做直接映射,每个节点负责一段连续的 slot 范围。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-009",
|
||
"type": "fill_blank",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"redis",
|
||
"sentinel"
|
||
],
|
||
"question": "Redis 哨兵(Sentinel)模式至少需要部署 ______ 个哨兵节点,以避免脑裂问题。哨兵通过类似 Raft 的协议选举 leader,当多数哨兵确认 master 不可达时触发故障转移。Sentinel 还负责 ______,即将新的 master 地址通知给所有客户端。",
|
||
"answer": [
|
||
"3",
|
||
"客户端通知",
|
||
"通知客户端",
|
||
"配置发布",
|
||
"发布新的 master 地址"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "Redis Sentinel 至少需要 3 个节点才能保证高可用,因为故障判定需要 quorum(多数派)同意。如果只有 2 个哨兵,任何一个挂掉都无法达成多数派,失去了容错能力。Sentinel 使用类似 Raft 的算法进行 leader 选举:当检测到 master 下线时,哨兵之间互相通信,通过投票选出 leader 来执行故障转移。故障转移完成后,Sentinel 通过「配置发布/订阅」机制(Pub/Sub)通知所有连接的客户端新的 master 地址,客户端会自动重连。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-010",
|
||
"type": "fill_blank",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"redis",
|
||
"hybrid-persistence",
|
||
"active-defrag",
|
||
"lru"
|
||
],
|
||
"question": "Redis 4.0 引入的混合持久化机制在 AOF rewrite 时,先以 RDB 格式写入当前全量数据,再追加 rewrite 期间的增量 AOF 命令,兼顾了 ______ 和 ______ 的优势。Redis 4.0 还引入了 ______ 功能,通过后台线程扫描并整理内存碎片,减少因频繁删改导致的内存浪费。当内存达到 maxmemory 时,Redis 根据 ______ 策略淘汰 key,常用策略包括 allkeys-lru、volatile-lru、volatile-lfu 等。",
|
||
"answer": [
|
||
"RDB 恢复速度",
|
||
"AOF 数据完整性",
|
||
"恢复速度",
|
||
"数据安全",
|
||
"active-defrag",
|
||
"active-defragging",
|
||
"内存淘汰"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "混合持久化(Hybrid Persistence)结合了 RDB 和 AOF 的优点:AOF rewrite 时先写 RDB 快照(恢复速度快),再追加增量 AOF 命令(保证数据完整性),大幅缩短了重启恢复时间。active-defrag 是 Redis 4.0 引入的主动内存碎片整理功能,通过后台线程对内存进行碎片扫描和重新分配,无需重启即可释放碎片内存,可通过 activedefrag yes 开启。Redis 的内存淘汰策略在内存达到 maxmemory 时触发:allkeys-lru 对所有 key 做 LRU 淘汰;volatile-lru 只对设了过期时间的 key 做 LRU;volatile-lfu 使用 LFU(最不经常使用)算法淘汰。LFU 比 LRU 更精准,能淘汰真正不活跃的 key。",
|
||
"source": null,
|
||
"related": []
|
||
}
|
||
]
|
||
} |