OceanBase带全局唯一索引表批量插入写入延迟过高的优化咨询
OceanBase v4.x MySQL模式全局唯一索引性能问题解决方案
1. 大批次导入时GSI写入/维护性能优化配置
OceanBase提供多个会话级和租户级配置,可针对性优化批量导入场景下的全局唯一索引(GSI)性能:
- 会话级参数
ob_enable_gsi_fast_path:开启后优化GSI批量写入的处理路径,减少分布式协调(如2PC)的开销,适合大批次插入场景,设置语句:SET ob_enable_gsi_fast_path = 1; - 会话级参数
ob_enable_batch_dml:开启批量DML优化逻辑,提升数据库对批量插入语句的处理效率,设置语句:SET ob_enable_batch_dml = 1; - 租户级参数
ob_gsi_build_in_background:若为离线迁移场景,可先禁用GSI完成批量导入,之后创建GSI时开启该配置,让GSI在后台异步构建,避免阻塞业务写入,需租户管理员执行:ALTER TENANT <tenant_name> SET ob_gsi_build_in_background = 1; - 调整批次大小:结合服务器内存情况,适当调大批次(如从500调整为1000),减少分布式锁的竞争次数。
2. 本地唯一索引对分区键的要求
OceanBase严格要求本地唯一索引的唯一约束必须包含分区键。
本地唯一索引的作用范围仅对应表的单个分区,若唯一约束不包含分区键,不同分区之间可能出现重复值,无法满足全局唯一性要求。因此,当业务键order_sn未包含分区键tenant_id时,无法通过本地唯一索引实现全局唯一,仅能保证单个租户分区内的order_sn唯一性。
3. 全局唯一性+低批量插入性能损耗的推荐模式
模式1:离线导入先禁GSI,导入后异步构建
适用于数据迁移等离线场景:
- 导入前删除或禁用GSI,以本地索引的性能完成批量写入;
- 导入完成后创建GSI,开启
ob_gsi_build_in_background让GSI在后台异步构建,不影响后续业务。
模式2:预生成全局唯一业务键,降低GSI冲突
- 使用分布式ID生成器(如雪花算法、OceanBase全局序列)预先生成全局唯一的
order_sn,插入前确保无重复; - 此时GSI仅承担索引查询作用,插入时几乎不会触发唯一性冲突检查的锁竞争,大幅提升批量写入性能。若业务允许,可将GSI改为普通全局索引(取消唯一约束),进一步降低开销。
模式3:业务层全局校验+本地唯一索引
若必须保留数据库层面的唯一性约束,可采用:
- 创建包含
tenant_id + order_sn的本地唯一索引,保证单租户分区内的唯一性; - 批量插入前,通过全局查询或Redis缓存快速校验所有待插入
order_sn的全局唯一性; - 插入时加分布式锁(如Redis锁)避免竞态问题,这种方式完全规避GSI的分布式协调开销,性能接近本地索引。
模式4:调整分区策略(业务允许时)
若业务逻辑允许,将order_sn与tenant_id共同作为哈希分区键,此时order_sn的唯一性可通过本地唯一索引保证(包含分区键),完全消除GSI的性能损耗,但需评估该分区策略是否符合业务的查询、隔离需求。
内容的提问来源于stack exchange,提问作者cui xiao
相关产品推荐
相关产品推荐

