OceanBase中INSERT INTO...SELECT启用direct load反而慢2.4倍的原因咨询
OceanBase Direct Load在INSERT INTO...SELECT中性能反降的问题分析与最佳实践
问题描述
测试OceanBase的direct load特性时发现,启用direct load的INSERT INTO...SELECT查询执行时间是传统路径的2.4倍。根据官方文档,direct load可绕过SQL层直接写入数据文件,理论上应具备更优的大规模数据导入性能,但实际测试结果与预期相悖。
环境信息
- OceanBase版本:OceanBase Community v4.3.5.0
- OLAP租户创建命令:
obd cluster tenant create obtest -n test --max-cpu=28 --memory-size=98G --zone-list=zone1,zone2,zone3 --primary-zone=RANDOM \ --locality=F@zone1,F@zone2,F@zone3 --charset=utf8 -s 'ob_tcp_invited_nodes="%"' --optimize=olap
- 调整的配置参数:
set global parallel_servers_target = 560; ALTER SYSTEM SET default_table_store_format = 'row'; SET GLOBAL parallel_degree_policy = MANUAL;
测试步骤
- 使用sysbench为3张表各准备1000万行数据
- 创建目标表
tmp1:CREATE TABLE tmp1 LIKE sbtest1; - 删除目标表主键的自增属性:
ALTER TABLE tmp1 MODIFY id int(11) NOT NULL; - 对比测试两种插入路径:
- 传统路径(10.24秒):
insert /*+ enable_parallel_dml parallel(16) no_direct */ into tmp1 select * from sbtest1;- Direct Load路径(24.42秒):
insert /*+ enable_parallel_dml parallel(16) DIRECT(true, 0, 'full') */ into tmp1 select * from sbtest1; - 添加
NO_GATHER_OPTIMIZER_STATISTICShint后性能无明显差异:insert /*+ enable_parallel_dml parallel(16) DIRECT(true, 0, 'full') NO_GATHER_OPTIMIZER_STATISTICS */ into tmp1 select * from sbtest1; -- 24.58秒 insert /*+ enable_parallel_dml parallel(16) no_direct NO_GATHER_OPTIMIZER_STATISTICS */ into tmp1 select * from sbtest1; -- 10.45秒
问题原因分析
- 数据规模不匹配:direct load的设计目标是超大规模数据导入(通常亿级以上),1000万数据量下,direct load的初始化开销、文件写入后的合并操作开销,反而超过了其绕过SQL层带来的收益;而传统路径依赖内存批量写入+提交,在中小数据量下效率更高。
- 存储格式适配问题:direct load对columnar存储格式的优化远优于row格式,本次测试中目标表使用row格式,无法发挥direct load的核心优势。
- 约束校验开销:目标表保留了主键约束,direct load需要额外执行全局唯一性校验,这部分开销远大于传统路径的批量校验逻辑。
- 并行度配置不合理:设置的
parallel(16)与direct load的调度机制不匹配,过高的并行度导致资源竞争,反而降低了写入效率。
Direct Load搭配INSERT INTO...SELECT的限制
- 仅在**超大规模数据(亿级以上)**场景下能体现性能优势,中小数据量下可能反降
- 对columnar存储格式优化显著,row格式下性能提升有限
- 目标表存在主键/唯一键时,会触发额外的全局唯一性校验,大幅增加开销
- 不支持带复杂计算、多表关联的SELECT语句,仅适合简单全表扫描或轻过滤查询
- 并行度需与集群资源匹配,过高或过低都会影响性能
最佳实践
- 选对数据规模:仅当导入数据量达到亿级以上时,再考虑使用direct load
- 使用columnar存储:创建目标表时指定
STORE_FORMAT='columnar',例如:CREATE TABLE tmp1 LIKE sbtest1 STORE_FORMAT='columnar'; - 临时移除约束:导入前删除目标表的主键、唯一键,导入完成后再重建,避免唯一性校验开销
- 优化并行度:根据集群CPU核心数调整并行度,建议设置为核心数的1-2倍,例如28核集群设置
parallel(28)或parallel(56) - 配合专业导入工具:direct load搭配外部导入工具(如OBLOADER)的效果优于
INSERT INTO...SELECT,工具会更高效地处理数据分块与写入调度 - 简化SELECT语句:避免在SELECT中加入复杂计算、多表关联,让direct load专注于数据写入环节
内容的提问来源于stack exchange,提问作者user30132773
相关产品推荐
相关产品推荐

