5~20 倍性能提升!GaiaDB 一次优化背后的秘密
伴随企业核心业务持续向云原生架构演进数据库正在从传统本地部署模式加速迈向存算分离架构。作为百度智能云自研云原生数据库GaiaDB采用存算分离设计实现计算与存储解耦在提供更高弹性与吞吐能力的同时也对复杂查询性能提出了更高要求。GaiaDB 支持大容量、高性能、高弹性场景并兼容 MySQL 生态。但在存算分离架构下数据页读写需要通过远程 RPC 完成相比传统本地磁盘呈现出明显的高延迟、高带宽这一特点。单次 IO 延迟可能从数十微秒提升至百微秒以上但整体并发吞吐能力远高于本地磁盘。随着查询规模增加大量同步远程 IO 容易成为影响查询性能的重要因素。针对这一挑战GaiaDB 推出了预读加速能力。通过提前预测后续需要访问的数据页并异步并行加载到内存GaiaDB 将原本同步等待的数据访问过程转变为主动准备。在典型业务场景下预读加速可实现520 倍性能提升加速后性能与本地盘持平甚至超出数倍。一句话概括查询还没开始数据已经提前就位。哪些场景收益最明显预读加速主要适用于存在大量同步远程 IO 的查询场景。通常来说扫描页数量越多、缓存命中率越低收益越明显。典型业务场景包括以下几类。查询历史或冷数据数据写入后长期未访问已经从内存中淘汰。例如查询用户 3 个月前的订单记录拉取去年的操作日志大范围时间区间扫描WHERE 条件跨越较长时间范围需要扫描大量索引页。例如create_time BETWEEN 2025-01-01 AND 2025-04-01深度分页当翻页位置较深时需要扫描并跳过大量数据。例如ORDER BY id DESC LIMIT 100000,20二级索引命中大量数据后回表通过非主键索引匹配大量记录后需要逐行回到聚簇索引获取完整数据。例如WHERE status 0 AND type 1当命中上万行时会产生大量随机访问。低频大表报表与统计查询后台跑批任务由于访问频率低数据大概率不在缓存中。例如每日凌晨对账汇总运营数据导出大表统计分析新实例启动后的首批查询实例启动或主备切换后Buffer Pool 为空所有访问都属于冷读。这些场景虽然表现形式不同但背后往往有同一个问题同步 IO 等待时间过长。所以核心优化策略不是“等数据变快”而是提前准备数据而不是等待数据。对此百度智能云 GaiaDB 预读加速基于 B 树逻辑结构提前预测后续访问的数据页并异步并行预取至内存从而消除逐页同步 IO 等待。整体来看预读加速主要覆盖两类核心查询路径主索引顺序扫描二级索引回表B 树逻辑预读先看目录再翻内容B 树逻辑预读适用于顺序扫描索引的业务场景例如大范围时间区间查询报表分析数据导出批量扫描类查询过去这类查询往往需要持续扫描大量索引页。一个报表可能耗时几十秒复杂场景甚至需要两分钟以上。开启索引逻辑预读后原本分钟级的查询可以缩短至秒级返回实现数倍性能提升。它的核心思路可以理解为先看目录再翻内容。当数据库执行大范围顺序扫描时逻辑预读不会等当前页面读取完成后再访问下一页。它会像翻书时先看目录一样提前查看索引上层节点获取接下来即将访问的数据页列表并一次性批量加载至内存从而大幅减少扫描过程中的等待时间。逻辑预读如何工作整个索引逻辑预读流程由 4 个核心模块协同完成按照触发 → 决策 → 执行 → 缓存这一链路逐层推进。模块一用户查询线程用户查询线程负责执行查询触发索引顺序扫描并识别预读边界。主要流程包括对数据库索引叶子页执行顺序扫描按照 Page100 → Page101 → Page102 → …… 的顺序持续推进在扫描过程中持续检测预读边界将触发信号传递至逻辑预读决策层。这一阶段负责正常查询执行同时也是整个预读机制的触发入口。模块二逻辑预读决策层逻辑预读决策层负责判断预读时机、筛选待预读页面并生成批量任务。主要流程包括边界条件检测判断当前扫描位置是否接近 Level-1 索引节点边界主动触发预读满足触发条件后主动读取下一个 Level-1 索引节点解析页面信息从 Level-1 节点中提取全部子页面指针缓存过滤过滤已经存在于 Buffer Pool 中的页面生成预读任务输出批量待预读页面列表并提交至异步 IO 层。这一阶段完成了从“发现下一批数据”到“确定真正需要读取哪些数据”的全过程。模块三异步 IO 层异步 IO 层基于 Gaia AIO 框架通过远程 RPC 并行请求数据充分利用云存储高带宽能力。主要流程包括基于 Gaia AIO 框架发起远程 RPC 调用将批量预读请求下发至存储节点实现多 IO 并行处理利用云存储高带宽特性提升整体 IO 吞吐效率IO 完成后通过回调机制通知 Buffer Pool 完成页面加载。这一阶段的关键价值在于把原本串行执行的数据读取过程改造成并行执行。模块四Buffer Pool 缓冲池Buffer Pool 负责缓存预读页面为用户查询提供高速访问能力。主要流程包括接收异步 IO 层完成加载的数据页将页面写入 Buffer Pool标记页面为可用状态后续用户线程访问该页面时直接命中缓存无需等待磁盘 IO。这一阶段相当于提前完成“数据备货”。当真正查询到来时数据已经准备完成实现了从查询等数据到数据等查询的转变。整个过程中原本“扫描一页、等待一次”的串行模式被重构为边扫描、边预取、边缓存。在数据量越大、扫描范围越广的场景下预读对 IO 等待的隐藏效果越明显加速收益也会进一步放大。二级索引回表预读提前准备“下一批要回表的数据”除了索引顺序扫描二级索引回表也是复杂查询中非常典型的性能瓶颈。二级索引回表预读适用于二级索引扫描后需要回表查询聚簇索引获取完整行数据的场景。例如按条件筛选 分页的列表查询通过索引字段过滤后再获取完整数据的业务 SQL二级索引命中大量记录后的批量回表查询在这类场景下查询通常需要频繁执行回表操作。随着命中记录数量增加同步 IO 等待会逐渐成为主要性能瓶颈。开启预读能力后可实现数倍甚至数十倍性能提升。它和索引逻辑预读有什么不同二级索引回表预读的核心思路是在主线程逐行执行回表的同时提前扫描后续二级索引记录预测后续回表目标页面并批量异步预读至 Buffer Pool。当主线程真正执行回表时目标页面已经提前加载到内存中从而消除同步 IO 等待。与索引逻辑预读不同两者关注对象存在明显差异类型关注对象索引逻辑预读当前索引自身后续即将访问的叶子页二级索引回表预读聚簇索引中回表目标对应的叶子页简单来说一个提前准备“下一批要扫描的数据”另一个提前准备“下一批要回表的数据”。二级索引回表预读如何工作二级索引查询异步预读整体涉及 4 个核心模块其中异步 IO 层和 Buffer Pool 与索引逻辑预读保持一致。核心差异主要在前两个阶段。模块一用户查询线程用户查询线程负责执行用户查询完成二级索引扫描与逐行回表并负责触发预读条件检测。关键流程包括顺序扫描二级索引记录按照 idx_rec1 → idx_rec2 → idx_rec3 → …… 持续推进根据二级索引记录中携带的主键信息逐行执行回表通过主键查询聚簇索引数据在扫描过程中持续检测预读触发条件达到预设阈值后向预读决策层发送触发信号。这一阶段主要负责“正常查询”同时承担预读触发入口角色。模块二预读决策与执行层预读决策与执行层是二级索引异步预读的核心控制单元负责完成预读流程调度、页面解析和目标筛选。主要流程包括提前扫描二级索引记录批量收集后续多条记录对应的主键值根据主键在聚簇索引中执行 Level-1 搜索解析并定位目标叶子页页号进行缓存过滤自动剔除已存在于 Buffer Pool 中的常驻页面汇总缺失页面列表整理为批量预读任务提交至异步 IO 层。这一阶段完成了从“记录”到“页面”的映射和筛选决定真正需要预取哪些数据。优化效果典型场景最高提速 18 倍为了验证预读加速效果GaiaDB 在统一机器规格和资源配置下对真实线上业务 SQL 进行了测试并排除了热数据影响。测试结果显示预读加速在多个典型场景中均取得明显收益。业务 SQL 场景本地盘耗时未开启预读耗时开启预读耗时加速效果条件过滤 排序查询0.26s0.76s0.05s相比未开启提升约 15 倍性能为本地盘 5 倍条件查询 LIMIT 120.25s3.88s2.07s相比未开启提升约 1.8 倍性能为本地盘 10 倍分组统计查询0.55s0.54s0.31s相比未开启提升约 1.8 倍多条件过滤 排序分页3.34s3.89s0.21s相比未开启提升约 18 倍性能为本地盘 16 倍时间区间查询 排序4.10s12.61s0.72s相比未开启提升约 17 倍性能为本地盘 5.5 倍整体来看预读加速能力相比原始版本实现了数倍至数十倍提升。随着同步读取页面数量持续增加性能优势还会进一步扩大。线上真实案例查询时间缩短至约 1/6目前预读加速能力已经在部分生产实例上线效果显著。案例一审计业务查询当天上午 SQL 记录业务场景查询当天上午所有实例的 SQL 审计 / 慢日志记录。SELECT id, database_ip, database_name, table_name,sqlFROM tb_001WHERE create_time BETWEEN 2025-05-01 AND 2025-05-01 12:00:00AND database_port 3300;优化效果上线前耗时预读加速后耗时提速倍数31.71s5.59s5.7x案例二跨天数据库操作审计记录回溯业务场景拉取跨天即 1.5 天的数据库操作审计记录用于月初回溯排查。SELECT id, database_ip, database_name, table_name,sqlFROM tb_001WHERE create_time BETWEEN 2025-04-01 AND 2025-04-02 12:00:00AND database_port 3300;优化效果上线前耗时预读加速后耗时提速倍数121.83s18.05s6.7x在上述场景中预读加速将查询时间缩短至原来的约 1/6。随着扫描数据量增加异步并行预读对 IO 等待的隐藏效果将更加明显加速收益也会持续放大。预读加速的本质是改变数据访问方式预读加速并不是简单提高读取速度而是改变了数据库的数据访问方式。它通过预测异步并行缓存将原本串行等待的数据访问过程升级为主动准备。也就是说GaiaDB 不再让查询被动等待数据而是让数据提前到位。从查询等数据变成数据等查询。在冷数据、大范围扫描、深分页以及复杂回表等典型场景下GaiaDB 预读加速实现了520 倍性能提升进一步释放了云原生数据库在复杂查询场景下的性能潜力。