全局二级索引与多活

共 19 题
📑 题目列表 19 题
#
★★★

1. 全局查询的优化器,CBO、统计信息?

分布式数据库的全局查询优化器如何工作?CBO(基于代价的优化)与统计信息的作用是什么?

  • CBO 优化器原理
  • 统计信息的作用
  • 分布式环境下优化器的挑战

全局查询优化器负责把分布式查询转换生成高效的执行计划。CBO(Cost-Based Optimizer,基于代价的优化)通过估算各执行计划的代价(利用统计信息估算基数、行数、IO、CPU、网络传输等),选择代价最小的计划。统计信息是 CBO 的基础,包括表/列的行数、基数、分布、索引信息等,用于估算选择率与代价。分布式环境下,优化器还需考虑数据分片分布、跨节点网络传输代价、是否可下推(谓词/投影/聚合下推减少传输),并结合各分片统计信息做全局估算。CBO 的准确性依赖统计信息的及时更新(如自动收集、采样)。

CBO 的核心是"用统计信息估算代价,选最优计划"。分布式查询优化比单机更复杂,因为要权衡网络传输与下推。统计信息过时会导致 CBO 选错计划。TiDB、CockroachDB 等都有 CBO 与统计信息收集机制。理解 CBO 与统计信息,是理解分布式查询性能调优的基础。

#
★★★

2. 分布式查询(Distributed Query)的下推(Pushdown),谓词、投影、聚合?

分布式查询(Distributed Query)的下推(Pushdown)是什么?谓词、投影、聚合如何下推?

  • 下推的概念
  • 谓词下推、投影下推、聚合下推
  • 下推减少网络传输

分布式查询的下推(Pushdown)指把查询中的计算尽量下推到数据所在的节点(各分片)执行,减少跨节点传输的数据量。常见下推:谓词下推(Predicate Pushdown)——把 WHERE 过滤条件下推到各分片,在各分片先过滤再返回,减少传输行数;投影下推(Projection Pushdown)——把需要的列下推,各分片只返回所需列,减少传输列数;聚合下推(Aggregation Pushdown)——把 GROUP BY/聚合部分下推到各分片做局部聚合,再在上层做最终聚合,减少传输量。下推的核心收益是"在网络侧少传数据、多利用各分片本地计算能力",显著提升分布式查询性能。

下推是分布式查询优化的关键手段,本质是"把计算移到数据所在地,减少数据流动"。谓词/投影/聚合三个下推分别减少行、列、聚合结果的数据量。TiDB、CockroachDB 等会把过滤、连接、聚合下推到各副本执行。理解下推能解释分布式查询的性能差异。

#
★★★

3. 跨分片 JOIN 的处理,广播 JOIN、Shuffle JOIN?

跨分片 JOIN 的处理方式有哪些?广播 JOIN(Broadcast Join)与 Shuffle JOIN 分别如何工作?

  • 广播 JOIN 的原理
  • Shuffle JOIN 的原理
  • 两种方式的适用场景

跨分片 JOIN 连接的数据分布在多个分片,需要特殊处理。广播 JOIN(Broadcast Join):把一个小表(如维度表)广播(复制)到所有分片,每个分片用本地的小表与本地的大表分片做 JOIN,避免大表数据移动。适合小表与大表 JOIN(小表能广播)。Shuffle JOIN(Repartition Join):把两个表按连接键重新分片(shuffle),使连接键相同的行落到同一分片,再在各分片本地 JOIN。适合两个大表 JOIN 或无法广播的场景。两者的权衡:广播 JOIN 传输小表、成本低,但要求小表足够小;Shuffle JOIN 需按连接键重分布数据、传输量大,但能处理任意大小表。分布式优化器会根据表大小自动选择。

跨分片 JOIN 的核心是"让连接键相同的行在同一个分片相遇"。广播用"复制小表"避免移动大表,Shuffle 用"按连接键重分布"保证连接键共位。选择取决于表大小与网络代价。这是 MPP/分布式数据库 JOIN 执行的基础。

#
★★★

4. 跨分片 JOIN 的代价,网络传输、数据倾斜?

跨分片 JOIN 的代价是什么?网络传输与数据倾斜如何影响跨分片 JOIN?

  • 跨分片 JOIN 的网络传输代价
  • 数据倾斜的影响
  • 代价的优化

跨分片 JOIN 的代价主要体现在网络传输与数据倾斜两方面。网络传输:跨分片 JOIN 需要把数据在分片间传输(广播小表或 shuffle 重分布),传输的数据量越大,代价越高,尤其在大表 JOIN 或跨地域时显著。数据倾斜:若连接键在某个分片上的数据量远大于其他分片(如热 key),该分片要处理大量数据成为瓶颈,导致 JOIN 执行缓慢、其他分片空闲等待(短板效应),整体性能严重下降。优化方式:选择合适的分片键让连接键均衡、用广播 JOIN 减少传输、对倾斜 key 做拆分(salt)、优化器避免大表 shuffle。跨分片 JOIN 的代价是分布式查询性能的关键瓶颈。

跨分片 JOIN 的代价本质是"数据移动 + 均衡性"。网络传输决定单次代价,数据倾斜决定最慢分片(决定整体耗时)。因此优化跨分片 JOIN 要"减少传输(广播/下推)+ 避免倾斜(均衡分片键、拆分热 key)"。理解这两类代价能有效调优分布式查询。

#
★★★

5. 跨分片 JOIN 的实现,广播、Shuffle、Lookup?

跨分片 JOIN 的实现方式有哪些?广播、Shuffle、Lookup 分别如何工作?

  • 广播 JOIN
  • Shuffle JOIN
  • Lookup JOIN

跨分片 JOIN 的主要实现方式:广播 JOIN(Broadcast)——把小表复制到所有分片,各分片本地 JOIN,适合小表与大表;Shuffle JOIN(Repartition)——把两个表按连接键重新分发到各分片,使连接键共位后本地 JOIN,适合大表;Lookup JOIN(索引/查询)——对每个大表行,通过查询(如缓存或索引)去小表/分片查找对应行,逐个连接,适合小表可被索引查询、无需全量传输的场景。三者的取舍:广播传输小表但要求小,Shuffle 处理任意表但传输量大,Lookup 避免全量传输但逐行查询开销大。优化器根据表大小、索引、数据量选择。

三种 JOIN 的核心差异是"如何让连接键共位"。广播复制小表、Shuffle 重分布、Lookup 按需查询。选择取决于表大小、数据分布与索引可用性。理解三种实现是设计分布式查询与优化 JOIN 的基础。

#
★★★

6. 全局二级索引(Global Secondary Index)的需求,跨分片查询?

全局二级索引(Global Secondary Index)的需求是什么?为何需要跨分片查询?

  • 全局二级索引的概念
  • 跨分片查询的需求
  • 全局索引与分片键的关系

分布式数据库中,数据按分片键分布到多个分片,主表按分片键可以快速定位数据。但业务经常需要按"非分片键"的列查询(如按用户 ID 分片、按邮箱查询),此时无法直接定位分片,只能广播到所有分片扫描(效率低)。全局二级索引(Global Secondary Index)为这些非分片键列建立全局索引,索引本身也分片(按索引键分片),查询时通过索引键定位到索引分片,再取得主键回表查主数据,从而避免全表广播。它解决了"按非分片键的跨分片高效查询"需求,是分布式数据库的关键能力(如 TiDB、CockroachDB、DynamoDB GSI)。

全局二级索引的需求源于"分片键固定,但查询维度多样"。没有全局索引,非分片键查询只能广播扫描,成本高。全局索引把"按索引键查询"也变成"按索引键路由",实现高效跨分片查询。代价是索引与主表的一致性维护。这是分布式数据库能否支持复杂查询的关键。

#
★★★

7. 分布式查询的执行模型,MPP(Massively Parallel Processing)?

分布式查询的执行模型 MPP(Massively Parallel Processing)是什么?如何并行执行?

  • MPP 的概念
  • 数据分片与并行执行
  • MPP 的适用场景

MPP(Massively Parallel Processing,大规模并行处理)是一种分布式查询执行模型:数据按分片键分布在多个节点(分片),查询时由协调节点(Coordinator)把查询计划下发到多个计算节点,各节点并行执行各自的子任务(过滤、投影、聚合、连接),再通过数据交换(broadcast/shuffle/repartition)汇总结果。MPP 通过"数据分片 + 并行执行 + 分布式算符"实现海量数据的并行处理,典型系统如 ClickHouse、TiDB、Presto、CockroachDB。其优势是横向扩展(增加节点提升吞吐)与并行计算能力。挑战是数据倾斜(某节点过载拖慢整体)、扩容与跨节点传输开销。

MPP 的核心是"把查询拆成可在多节点并行执行的子任务,通过数据交换汇总"。它是分布式数据库/数仓执行大数据查询的模型。理解 MPP 的分片、并行、交换,以及其数据倾斜与扩容挑战,是理解分布式查询性能的基础。

#
★★★

8. 在线扩容(Online Scale-Out)的实现,TiDB、CockroachDB、YugabyteDB?

在线扩容(Online Scale-Out)在 TiDB、CockroachDB、YugabyteDB 中如何实现?

  • 在线扩容的概念
  • TiDB/CockroachDB/YugabyteDB 的扩容
  • 扩容与再平衡

在线扩容(Online Scale-Out)指在不中断服务的情况下,通过增加节点提升系统容量与吞吐。TiDB、CockroachDB、YugabyteDB 都支持在线扩容:新增节点加入集群后,系统自动把数据(Region/Tablet/分片)按负载重新调度到新节点(数据再平衡),迁移过程对应用透明、不中断写。TiDB 通过 PD(Placement Driver)调度 Region 迁移;CockroachDB 通过 range 自动分裂与迁移;YugabyteDB 通过 tablet 在节点间迁移。扩容时系统自动均衡各节点负载与数据量,并处理热点。在线扩容要求系统具备"动态分片 + 自动迁移 + 无感知切换"能力,这是分布式数据库横向扩展的核心价值。

在线扩容的关键是"数据自动再平衡 + 服务不中断"。三个系统都通过元数据调度器(PD/协调器)把分片在节点间迁移,实现扩容。相比传统分库分表需人工迁移,这类系统把扩容自动化。理解在线扩容机制,是理解分布式数据库弹性能力的核心。

#
★★★

9. 弹性扩缩容(Elastic Scaling)的需求,流量波动?

弹性扩缩容(Elastic Scaling)的需求是什么?如何应对流量波动?

  • 弹性扩缩容的概念
  • 流量波动的场景
  • 弹性扩缩容的实现

弹性扩缩容(Elastic Scaling)指系统根据实时流量或负载动态地增加或减少资源(节点),以应对流量波动。需求源于业务流量具有波动性(如电商大促、秒杀、节假日高峰、夜间低谷),静态固定容量要么资源浪费(低谷闲置),要么高峰不足(过载)。弹性扩缩容通过监控负载指标(CPU、QPS、延迟),达到阈值时自动扩容(加节点)或缩容(减节点),并伴随数据再平衡、路由更新。它追求"容量与负载匹配",既保证高峰可用性又不浪费资源。实现依赖分布式系统的自动调度、数据迁移与快速调整能力。

弹性扩缩容是"按需分配资源"的云原生理念。其核心是"监控 → 触发 → 调整(加减节点 + 数据再平衡)"。与在线扩容相关,但更强调"动态收缩"与"成本优化"。缩容需注意数据安全。理解弹性扩缩容能设计高可用低成本系统。

#
★★★

10. 数据再平衡(Data Rebalance)的策略,均匀分布、业务感知?

数据再平衡(Data Rebalance)的策略有哪些?均匀分布与业务感知如何取舍?

  • 数据再平衡的概念
  • 均匀分布策略
  • 业务感知策略

数据再平衡(Data Rebalance)指数据分布变化时,重新分配数据以保持各节点负载均衡。策略:其一,均匀分布——按数据量/分片数把数据尽量均匀分配到各节点,追求"每个节点数据量接近",简单但可能因热点(某 key 访问量大)导致负载不均;其二,业务感知(负载感知)——不仅看数据量,还考虑各分片的实际访问负载(读写 QPS、热点),把热数据/热分片迁移或拆分到负载低的节点,实现"负载均衡"而非"数据量均衡"。两者取舍:均匀分布实现简单、迁移少,但可能负载不均;业务感知更精确但需监控负载、迁移频繁、成本高。实际系统常结合两者,先均匀分布,再按负载动态调整。

再平衡的目标是"让节点负载均衡",而不仅是数据量均衡。均匀分布是基础,业务感知处理热点。理解两者的差异,能解释为什么有些系统会迁移热点数据。数据再平衡是扩容、热点处理、故障恢复的基础机制。

#
★★★

11. 单元化(Cell-Based)架构,用户绑定到特定单元?

单元化(Cell-Based)架构是什么?用户如何绑定到特定单元?

  • 单元化架构的概念
  • 用户绑定与路由
  • 单元化与容灾

单元化(Cell-Based)架构把系统按业务/用户维度划分成多个独立的单元(Cell),每个单元是一个自包含的可用区(包含自己的服务、数据库、缓存),用户/流量通过某种规则(如用户 ID 哈希、地域)被绑定到某个特定单元上,该用户的所有请求都路由到其所属单元处理。其好处:一是隔离与故障域——单个单元故障不影响其他单元;二是容灾与扩展——可按单元整体部署、迁移、扩容;三是多活——不同单元可同时对外服务(阿里的单元化实践)。用户绑定通过路由表/哈希(如用户 ID 取模)实现,需保证单元内数据自包含(数据按用户维度分片,避免跨单元依赖)。单元化架构适合用户量巨大、可水平切分的业务。

单元化架构的核心是"按用户维度切分 + 单元自包含 + 路由绑定"。它把"整个系统"变成"多个独立可部署的单元",提升隔离性、扩展性与容灾能力。用户绑定是路由的关键,需保证单元内数据完整。这与多活和分片相关,是大型互联网架构的重要模式。

#
★★★

12. 多活(Multi-Active)的概念,多个数据中心同时对外服务?

多活(Multi-Active)的概念是什么?多个数据中心如何同时对外服务?

  • 多活的概念
  • 多数据中心同时服务
  • 多活的挑战

多活(Multi-Active)指多个数据中心(或单元)同时对外提供服务,而不是一主一备(冷备/温备)。在"单点写、多点读"的多活中,一个中心负责写,其他中心负责读,故障时切换;在"真多活"中,多中心都能写,但需解决冲突与一致性问题。多活的收益是充分利用资源(所有中心都服务)、提升可用性(单中心故障不影响)、降低故障恢复时间。多活的挑战:数据一致性(多中心复制延迟、冲突解决)、会话与路由(用户请求路由到正确中心)、时钟与幂等、故障切换与回切。多数系统选择"单点写、多点读"接受"多活"部分能力,真双写需满足严格前提。

多活的核心是"多个中心同时服务",区别于主备。它的价值是资源利用与可用性,挑战是数据一致与路由。多活的复杂程度取决于"是否允许多点写"。理解多活的概念与挑战,是设计跨地域高可用架构的基础。

#
★★★

13. 全局二级索引如何保证与主表数据一致?TiDB 等系统为何用分布式事务或异步回填构建索引,写入放大如何控制?

全局二级索引如何保证与主表数据一致?TiDB 等系统为何用分布式事务或异步回填构建索引?写入放大如何控制?

  • 全局索引与主表一致性
  • 分布式事务/异步回填建索引
  • 写入放大控制

全局二级索引与主表分属不同分片,必须保证两者数据一致。TiDB 等系统通过绑定主表写入与索引写入来保证一致性:写主表时,用分布式事务(在同一事务内同时写主表与索引,原子提交)或在索引构建时用异步回填(后台扫描主表数据,为索引补数据)。建索引时,若用同步方式(边写边建)会阻塞长事务,因此常采用异步回填:先建索引骨架,后台任务从主表扫描数据回填索引,期间新写入通过捕获/合并到索引,最终对齐。写入放大控制:因为写主表要同时写索引(每行写多个索引),写入放大明显。控制手段:只建必要索引、减少索引数、用批量/批量回填、异步合并、合理选择索引列。全局索引的一致性保证是分布式数据库的关键能力。

全局索引一致性要求"主表改动与索引改动原子"。TiDB 用分布式事务(写主表+写索引同事务)保证在线一致性,用异步回填保证建索引不阻塞。写入放大是索引的固有代价,需通过控制索引数量与批量写来缓解。理解这些能合理设计全局索引并评估其成本。

#
★★★

14. 多活架构中为什么多数系统选择单点写、多点读而非真双写?真双写需要满足哪些前提(冲突消解、时钟、幂等)?

多活架构中为什么多数系统选择单点写、多点读而非真双写?真双写需要满足哪些前提?

  • 单点写多点读 vs 真双写
  • 真双写的冲突消解
  • 时钟、幂等前提

多数系统选择"单点写、多点读"而非真双写,因为真双写(多中心同时写)会引入大量复杂性:写冲突(同一数据被多中心同时改)、数据一致性(多中心复制冲突)、时钟同步(判断先后)、幂等(重复处理)、以及故障切换与回切时的复杂性。真双写需要满足严格前提:冲突消解——需要可靠的冲突检测与解决策略(如 LWW、版本号、向量时钟);时钟——多中心需要可比较的时钟(或 HLC/逻辑时钟)以判断写序;幂等——写操作要幂等,避免重复执行;以及数据分片与路由保证同一数据在主写中心。这些前提的实现成本高、风险大,而"单点写、多点读"只需复制(读可从多中心读)即可获得大部分多活收益(多中心读、资源利用),写仍单点但简单可靠。因此多数系统用"单点写多点读"作为务实的多活方案。

真双写的代价是"冲突解决 + 时钟 + 幂等"的复杂性与高风险,而单点写多点读用"写单点 + 读多中心"规避冲突,获得多活大部分收益。这是"正确性优先于便利"的工程取舍。理解真双写的前提,能合理解释为何主流系统采用单点写多点读。

#
★★

15. 异地多活的冲突解决,最后写入获胜(LWW)、向量时钟?

异地多活的冲突解决办法有哪些?最后写入获胜(LWW)与向量时钟如何工作?

  • LWW 冲突解决
  • 向量时钟
  • 冲突解决的取舍

异地多活(多中心同时写)的冲突解决策略:最后写入获胜(LWW,Last-Write-Wins)——为每个写操作附加时间戳/版本号,冲突时取时间戳最新(或版本最大)的写入,简单高效但可能丢失旧写入(时间戳相同的无法区分,且依赖时钟);向量时钟(Vector Clock)——每个节点维护一个向量,记录每个节点的版本计数,冲突时比较向量可判断因果并发关系,能准确判断并发写并保留冲突(需人工/应用合并),但向量开销大、随节点数增长、冲突分支可能累积。此外还有版本号、CRDT 等。取舍:LWW 简单、收敛快,适合可接受丢更新的场景;向量时钟精确但复杂、开销大。实际系统(如 DynamoDB、Cassandra)常用 LWW 或版本号 + 可调一致性。

冲突解决的核心是"判断并发写并决定如何收敛"。LWW 用时间戳简化,但丢更新;向量时钟能精确判断并发但复杂。选择取决于业务对"丢更新"的容忍度。"最后写入"需要可靠的时钟,否则判断失准。理解冲突解决是理解异地多活最难点的基础。

#
★★

16. MPP 模型如何通过数据分片与并行执行扩展,其扩容与数据倾斜的挑战是什么?

MPP 模型如何通过数据分片与并行执行扩展?其扩容与数据倾斜的挑战是什么?

  • MPP 的扩展机制
  • 扩容的挑战
  • 数据倾斜的挑战

MPP 通过数据分片与并行执行扩展:数据按分片键分布到多个节点,查询时各节点并行执行子任务,通过数据交换(broadcast/shuffle)汇总,增加节点即可提升并行度与吞吐(横向扩展)。挑战:其一,扩容——新增节点需要把数据重新分片/迁移到新节点(数据再平衡),迁移过程要控制对在线服务的影响、避免长时迁移,且扩容后要重新均衡;其二,数据倾斜——若分片键分布不均或存在热 key,某节点承担过度负载成为瓶颈,其他节点空闲,整体性能受制于最慢节点(短板效应),导致查询延迟高、扩展性受限。应对倾斜:均衡分片键、拆分热 key(salt)、按负载动态调度、动态分片。扩容倾斜是 MPP 大规模扩展的两大核心挑战。

MPP 的扩展性来自"分片 + 并行",但扩容的迁移与数据倾斜会限制扩展效果。扩容要"平滑再平衡",倾斜要"均衡分片"。理解这两大挑战,能解释分布式系统在海量数据下面临的性能瓶颈与优化方向。

#
★★

17. 不用全局二级索引时有哪些替代方案,冗余表、广播小表、应用层维护索引各自的维护成本与一致性风险?

不用全局二级索引时有哪些替代方案?冗余表、广播小表、应用层维护索引各自的维护成本与一致性风险是什么?

  • 冗余表方案
  • 广播小表方案
  • 应用层维护索引

不用全局二级索引时,可用替代方案:其一,冗余表——把需要查询的维度数据冗余一份到按该维度分片的表(如按邮箱分片的用户表),查询走冗余表。维护成本低(同库写入),但需维护双写一致性(冗余表与主表同步,可能不一致)、额外存储。其二,广播小表——把小的维度表复制到所有分片,各分片本地查询。成本低(小表),适合小表,但小表更新需广播同步(一致性风险)。其三,应用层维护索引——应用在写入时同时维护一个索引结构(如 Redis 索引、KV),查询先查索引再查主表。灵活但需应用保证"主表写入 + 索引更新"的原子性(否则索引与数据不一致),且索引维护成本高、易丢失/不一致。这些方案都绕开全局索引,但以"手动维护一致性"或"功能受限"为代价,一致性风险高于数据库内置的全局索引。

替代方案的目的是"在无全局索引时实现某些查询",但都以"手动同步一致性"为代价。冗余表双写、广播表同步、应用索引都要保证一致性,易出错。相比数据库内置全局索引(自动保证一致性),这些方案维护成本高、一致性风险大,适合简单场景或全局索引不可用的场景。理解其取舍能选择合适方案。

#

18. 缩容(Scale-In)的安全考量?

缩容(Scale-In)的安全考量是什么?缩容时需要注意哪些问题?

  • 缩容的风险
  • 数据迁移与安全
  • 缩容的流程

缩容(Scale-In)指减少节点,需谨慎处理数据安全。安全考量:其一,数据迁移——缩容的节点数据必须完整迁移到剩余节点,且保证迁移后数据不丢失、不重复、一致;其二,数据冗余——缩容后需保证剩余节点仍满足副本数/冗余要求(如 Raft 多数派、副本数),否则降低容灾能力;其三,容量评估——缩容前评估剩余节点容量能否承载全部数据与负载,避免缩容后过载;其四,流量与路由——缩容期间更新路由,避免请求打到已下线节点;其五,回滚——缩容失败需能回滚。缩容流程:评估容量 → 迁移数据 → 校验一致 → 下线节点 → 更新路由 → 验证。缩容比扩容更需谨慎,因为减少冗余会降低可用性。

缩容的安全核心是"数据不丢 + 冗余不减 + 容量够用"。缩容改变数据分布,必须保证迁移完整、副本足够、节点不超载。相比扩容,缩容风险更高(减少冗余)。理解缩容的安全考量,是进行弹性缩容的前提。

#

19. 多活切换后的回切(failback)如何避免数据冲突?旧主追平校验与双写窗口的处理流程是什么?

多活切换后的回切(failback)如何避免数据冲突?旧主追平校验与双写窗口的处理流程是什么?

  • 回切(failback)的流程
  • 旧主追平校验
  • 避免双写窗口

多活切换后的回切(failback)指把业务从临时新主切回原主(或重新规划)的过程。为避免数据冲突,流程:其一,确认旧主恢复,把旧主挂为新主的从库/通过复制补拉日志,使其追平到与新主一致(追平校验,比对复制位点/校验和);其二,确认两侧数据一致后,在低峰期执行回切,把写流量切回旧主;其三,关闭双写窗口——回切期间绝不允许新旧主同时写入(避免冲突),必须先停写(或保证单点写)再切换;其四,回切后验证业务与数据,并将新主降为从库。核心是"追平校验 + 单点写(避免双写窗口)"。多活场景下,若旧主在故障期间缺失数据无法追平,需先处理数据合并或差异,再回切。

回切避冲突的关键是"先追平校验,再单点写切换,避免双写"。双写窗口是回切时数据冲突的最大来源,必须通过先停写、后切换来消除。追平校验保证旧主数据不缺。理解回切流程,是多活运维的基础。