NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

数据库使用 SQL*Loader 导入的并行误区,如何巧妙规避?

  • 2019-08-02
  • 本文字数:2186 字

    阅读完需:约 7 分钟

数据库使用SQL*Loader导入的并行误区,如何巧妙规避?

本文由 dbaplus 社群授权转载


本文中的 SQL*Loader 案例源于几年前数据库一体机 PK 测试的场景,场景比较特殊,在疯狂的 PK 中,方案不断迭代升级,使得案例有一定的趣味性。近期又碰到客户在弄 SQL*Loader 的导入,老案例整理下分享一波。

一、大数据量超宽表导入

该 SQL*Loader 测试场景如下:


将一个包含约数亿行数据的 txt 文件(不可切分文件),使用 SQL*Loader 导入到数据库中,表约有 200+列,不能改数据库层面配置,统计上机操作到导入完成的时间计算成绩,数据量不对该场景直接计 0 分。


当时的最新款 exadata x5 测试该场景计时约 40 分钟(直接路径,Parallel,BINDSIZE 等该优化的都优化了),这个场景我测出来约 10min,远超所有竞争对手的成绩,那究竟是什么操作能有如此大性能提升呢?

1、并行误区

当时由于甲方测试方案中限制不能拆分文件,导致大家测试时没有开启并行,那么 SQL*Loader 是否一定要拆分文件后才能进行并行呢?当然不是,这个场景中出了第 1 版本的方案:


  • wc -l 统计数据行数;

  • 配合 skip + load 生成多条命令逻辑上 进行切分文件;

  • 批量并行执行命令导入数据。


生成 SQL*Loader 的命令可以使用以下脚本,其中 total line number 取 wc -l 的结果,DOP 为自定义并行度:


  set serveroutput on    set linesize 1000    set pages 0    declare    total_line_number number;    dop  number;    skip  number;    load  number;    tail_of_mod  number;    command varchar2(4000);    directory varchar2(4000);    begin    total_line_number := 348104868;    directory := '/home/oracle/adam';    dop := 20;    skip := 0;    load := 0;    tail_of_mod := mod(total_line_number,dop);    load := trunc(total_line_number/dop);    for i in 1..dop loop    if i = dop then     load := load + tail_of_mod;    end if;    command := 'nohup sqlldr tester/tester control='||directory||'/load.ctl log='||directory||'/test'||i||'.log READSIZE=20000000 BINDSIZE=20000000 direct=true parallel=true  errors=99999 silent=errors,discards skip='||skip||'   load='||load ||' &' ;    dbms_output.put_line(command);    skip := skip+load;    end loop;    end;    /
复制代码


当时测试 SQL*Loader 场景时,故意最后一个测试,方案报上去,甲方就补充了一条规则,数据量不对该场景直接 0 分。


经历过后面的场景后发现,当时确实是运气还不错,改进版方案应对的坑当时都没踩到。这个场景中,表的列特别多,其实导入过程中瓶颈并不是 IO,而是 CPU,这也才使得逻辑切分的方法非常适合使用。


那么如果是 IO 为瓶颈呢?可能这种方式并不太合适。对于有高性能存储的环境,测试发现单进程压测可以达到峰值 60%的 IOPS,也就是多进程能带来的 IO 上的提升很有限,同时 skip 操作,其实会产生无用的读操作,同时也消耗 IO 资源,综上 IO 为瓶颈的导入采用这种方式可能大打折扣。

二、超大数据量导入

这个场景有趣的地方就在于,如果你没看上面的那波操作,导入会一帆风顺…场景描述起来很简单:SQL*Loader 单表导入 6T 的文本文件,条件也一样不能拆分文件。


只是这次稍微有点不一样的就是,有环境测试,气氛没那么紧张。但按照老的方案上来,第一步就坑了。之前的场景中,wc 统计那步大约 3 分钟就完成了。而这次 wc 搞了两个小时还没弄完,不得不感叹这个厕所上的时间有点长啊。


很想抽根烟,可惜我不会,只能老实的 cancel 掉再来改进方案。很快我发现其实可以这样。

1、改进方案

  • 在 wc 统计总行数的过慢的时候,可采用估值方式。head -n 50000 xxxx.file > 1.txt;

  • 大文件的字节/小文件的字节数 * 采样样数,可以近似估算出一个总数;

  • 最后一个 Job 不用写 load 数,即为全部加载。


看上去这个方案还是不错,执行下来也还 ok。

2、重大 bug

只是跟甲方汇报的时候,发现了一个大问题,数据对不上!我反思了一下方案,没找到逻辑上的毛病,查了日志,也没问题,只能重新再导入一次,还是 4294967295 这个数值,比甲方提供的数据少几个亿。


作为 Oracle 的 DBA,一个常识就是当你遇到不合理,解释不通的问题时候,MOS 上的 bug 列表永远不会让你失望,印象中拿着 4294967295 这个幸运数字马上定位到了文档 id(1161183.1) SQL*Loader Fails To Load More Than 4294967295 (2^32 - 1) rows From An External Data File 参考下图:



简单来说就是:每命令只能 load 约 42 亿数据,加上 skip 约 65 亿。12c 后才修改这个 bug,当时主流版本时 11.2.0.4 所以这个任务不拆分文件 SQL*Loader 应该是搞不定的。

三、总结

对于 SQL*Loader 导入场景中,skip + load 实现并行的导入的方式对于 CPU 消耗大的导入(涉及很多的单行拆分)还是有适用场景的,但有对于 IO 密集型的导入,可能需要测试以及规避 bug。当然如果没硬性限制的话,很多场景可以考虑直接用外部表。


作者介绍


蒋健,云趣网络科技联合创始人,11g OCM,多年 Oracle 设计、管理及实施经验,精通数据库优化,Oracle CBO 及并行原理。云趣鹰眼监控核心设计和开发者,资深 Python Web 开发者。


原文链接


https://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650779518&idx=2&sn=08c456ecb524111099bee96f28756db6&chksm=f3f91aebc48e93fd8c40705cf2b218ef9592e5ec9c0f65eefeeebc12d2a54ab81c135a7a4704&scene=27#wechat_redirect


2019-08-02 08:002419
用户头像
dbaplus社群 数据连接未来

发布了 176 篇内容, 共 71.2 次阅读, 收获喜欢 599 次。

关注

评论

发布
暂无评论
发现更多内容

什么是Python中的套接字编程?

华为云开发者联盟

Python 编程 socket 网络 套接字

文档代码同源

不脱发的程序猿

开发规范 文档代码同源

缓存的世界Redis(一)

卢卡多多

redis 缓存 6月日更

互联网就业系列文(一)

HZFEStudio

互联网 就业

详解Vue八大生命周期钩子函数

华为云开发者联盟

Vue 对象 函数 Vue实例 八大生命周期

Python——元组的使用

在即

6月日更

Apache Drill 1.19.0 发布集锦

MPP Apache Drill 联邦查询和分析

【LeetCode】山脉数组的峰顶索引Java题解

Albert

算法 LeetCode 6月日更

网络安全逐渐成为程序员的必备技能

学神来啦

Linux 程序员 安全 渗透

EMQ映云科技边缘计算里程碑—Kuiper加入LF Edge基金会

EMQ映云科技

开源 云端 边缘流式数据 emq LF Edge

实时音视频开发理论必备:如何省流量?视频高度压缩背后的预测技术

JackJiang

音视频 即时通讯 IM 视频编解码

敏捷绩效管理三剑客:OKR 、KPI、CFR

CODING DevOps

DevOps OKR 敏捷绩效 绩效管理

vue编码之优化手段

法医

Vue 大前端 6月日更

EasyRecovery用法进阶--高阶设置使用技巧

淋雨

数据恢复 EasyRecovery 文件恢复 硬盘恢复

Go 语言学习路线来啦

roseduan

学习 Go 语言

云图说|华为云自研云数据库GaussDB NoSQL,兼容多款NoSQL接口的数据库服务

华为云开发者联盟

nosql Influxdb Cassandra mongo GaussDB NoSQL

[译] Android 的 Java 9,10,11,12 的支持

Antway

6月日更

ARTS 打卡第11周

steve_lee

【Flutter 专题】127 图解基础 Image 小组件

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 6月日更

浪潮云说丨云应用容灾:四大关键能力,护航业务连续性

浪潮云

云计算

并发王者课-黄金3:雨露均沾-不要让你的线程在竞争中被“饿死”

MetaThoughts

Java 多线程 并发 并发王者课

Pandas高级教程之:Dataframe的重排和旋转

程序那些事

Python 数据分析 pandas 程序那些事

你应该知道的数仓安全

华为云开发者联盟

数据加密 数仓安全 透明加密 SQL函数加密

react源码解析12.状态更新流程

全栈潇晨

React

ONES CTO 冯斌 | 大型软件研发团队如何实践高效项目管理?

万事ONES

团队管理 ONES Project 研发团队

ONES CTO 冯斌 | 升级项目管理体系,加速金融行业数字化转型

万事ONES

项目管理 研发管理 数字经济 ONES

【译】JavaScript 代码整洁之道-概述篇

KooFE

JavaScript 大前端 6月日更 整洁代码

推荐学Java——应该了解的前端内容

逆锋起笔

Java 大前端 后端 JAVA开发

重启心智解锁,重新获得一份能力精进指南,面对不确定性的未来,我们可以和世界的变化做好友。

叶小鍵

你有一份Rx编程秘籍请签收

vivo互联网技术

响应式编程 大前端 函数编程 RXJS

docker搭建Nginx和Tomcat负载均衡

叫我阿柒啊

nginx Docker 负载均衡

数据库使用SQL*Loader导入的并行误区,如何巧妙规避?_数据库_dbaplus社群_InfoQ精选文章