在数据抽取中常用到从其他数据库抽取数据后数据灌入到hive数据库的情况。
大体逻辑是,连接源数据库,抽取数据,缓存转换,数据插入到hive数据库(或者直接覆盖db文件)。
中间源数据库的效率和代码质量、抽取数据的服务器资源、数据转换的效率、hive数据的插入sql效率等都是限制数据抽取效率的瓶颈,如何在保证系统稳定的情况下,效的优化各阶段的运行速度,从而整体提高数据抽取的效率,是一个比较大的课题。
从三个方面做思考:源数据库优化,抽取过程优化,数据灌入优化
源数据库优化
数据在抽取源数据库的时候,根据table是否有索引,视图代码是否有优化等,在源数据库本身对源表(视图)代码进行优化
抽取过程优化
使用spark或平台工具对源数据库抽取,对spark和平台的优化设置
spark优化
spark并行抽取数据
连接Oracle数据库抽取数据,spark可以更细致的控制并行抽取数据
dbconf的设置
var DBconf = Map(
"url" -> url,
"user" -> username,
"password" -> password,
"fetchsize" -> "100",
"upperBound" -> "150000000",
"lowerBound" -> "1",
"numPartitions" -> "10",
//"partitionColumn" -> "ROW_ID",
"partitionColumn" -> "rn",
"driver" -> driver
)
具体含义如下
partitionColumn: 分区字段,需要是数值类的(partitionColumn must be a numeric column from the table in question.), 经测试,除整型外,float、double、decimal都是可以的 **必须是sql中存在的字段名(别名也可以吧),否则会报错 分区列得是数字类型;所谓的并行读取其实就是开了多个数据库连接,分块读取的。 lowerBound: 下界,必须为整数 upperBound: 上界,必须为整数 numPartitions: 最大分区数量,必须为整数,当为0或负整数时,实际的分区数为1; 并不一定是最终的分区数量, 例如“upperBound - lowerBound< numPartitions”时,实际的分区数量是“upperBound - lowerBound”; 在分区结果中,分区是连续的,虽然查看每条记录的分区,不是顺序的,但是将rdd保存为文件后,可以看出是顺序的。 **以上四个值必须同时有指定,或都不指定,否则会报错 如果一个表分10个分区读取,id为分区列,其值从0-101,但是设置的lowerBound是1,upperBound是100,那么读取的规则如下: 第一个分区:select * from tablename where id<=10; 第二个分区:select * from tablename where id >=10 and id<20; 第三个分区:select * from tablename where id >=20 and id <30; …… 第十个分区:select * from tablename where id >=90;// 即一次读取100条数据,分10个区来平均读取,每个分区读取(upperBound-lowerBound)/numPartitions=(101-1)/10的条数量 从这里立即,numPartitions字段最好是连续的数字,这样可以保证每次每个分区读取的数据是饱满的,oracle中建议使用rownum
参考连接
Spark读写Oracle性能深度调优_rowid自定义分区键-CSDN博客
如何理解SparkSQL中的partitionColumn, lowerBound, upperBound, numPartitions_spark numpartitions-CSDN博客
spark sql代码优化
即调用的sql实际上是在Oracle数据库执行,所以可以利用Oracle 特性执行一些优化策略。
服务器资源优化
数据灌入优化
数据抽取和转换后,开始进入hive数据库,此时的一些优化建议
hive sql优化
在使用hive sql插入表的时候,启用一些优化设置,可以有效的提高insert的效率
set mapreduce.map.memory.mb=2048;--2gb--设置map任务的内存大小
set mapreduce.reduce.memory.mb=2048;--2gb--设置reduce任务的内存大小
set hive.exec.dynamic.partition.mode = nonstrict;
--开启非严格模式,允许所有分区都是动态的,否则必须要有一个静态分区
set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set mapred.max.split.size = 51200000;--50m
--每个Map最大输入大小
set mapred.min.split.size.per.node=51200000;--50m
set mapred.min.split.size.per.rack=51200000;--50m
set hive.exec.reducers.max = 128;--最大的 reduce 数
--开启map join
set hive.auto.convert.join = true;
set hive.mapjoin.smalltable.filesize = 62500000;--单位Byte 62.5m
set mapred.job.name = ads_fm_ma_xxmaexpallodtl_di_mm;--设置job名字,可以yarn里方便查阅
--设置任务名称
spark优化
有两种方式:使用spark sql插入hive数据库和直接覆盖hdsf的服务器DB文件
spark sql插入
可以在spark sql中执行hive sql的相关优化