Spark入Hbase的四种方式效率对比
一、方式介绍
本次测试一种采用了四种方式进行了对比,分别是:1.在RDD内部调用java API。2、调用saveAsNewAPIHadoopDataset()接口。3、saveAsHadoopDataset()。4、BulkLoad方法。
测试使用的大数据版本如下(均为单机版):Hadoop2.7.4、Hbase1.0.2、Spark2.1.0
二、测试
本次测试采用10W条单一列簇单一字段固定值进行测试。
以下是测试结果:
1.JAVA API
10W条数据:1000ms、944ms
100w条数据:6308ms、6725ms
2.saveAsNewAPIHadoopDataset()接口
10W条数据:2585ms、3125ms
100w条数据:13833ms、14880ms
3.saveAsHadoopDataset()接口
10W条数据:2623ms、2596ms
100w条数据:14929ms、13753ms
4.BulkLoad方法(此方法是导入大量数据最好的选择!!!)
10W条数据:9351ms、9364ms
100w条数据:9342ms、9403ms
1000w条数据:9690ms、9609ms
三、代码
pom引用
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-common</artifactId>
<version>1.0.2</version>
</dependency> 1)javaAPI代码
-------------------------------------
package cn.piesat.app import java.text.DecimalFormat
import java.util.{ArrayList, List, Random} import org.apache.hadoop.hbase.{HBaseConfiguration, HColumnDescriptor, HTableDescriptor, TableName}
import org.apache.hadoop.hbase.client._ object SparkJavaApi {
val ZOOKEEPER_ADDRESS = "hadoop01"
val ZOOKEEPER_PORT = "2181"
val df2: DecimalFormat = new DecimalFormat("00") def main(args: Array[String]) = {
val tableName: String = "test01"
val conn = getConn
val admin = conn.getAdmin
val putList = getPutList()
if (!admin.tableExists(TableName.valueOf(tableName))) {
createTable(admin, tableName, Array("cf"))
}
val start: Long = System.currentTimeMillis
insertBatchData(conn,tableName,admin,putList)
val end: Long = System.currentTimeMillis
System.out.println("用时:" + (end - start))
} def getConn(): Connection = {
val conf = HBaseConfiguration.create
conf.set("hbase.zookeeper.quorum", ZOOKEEPER_ADDRESS)
conf.set("hbase.zookeeper.property.clientPort", ZOOKEEPER_PORT)
ConnectionFactory.createConnection(conf)
} def insertBatchData(conn: Connection, tableName: String, admin: Admin, puts:List[Put]) = try {
val tableNameObj = TableName.valueOf(tableName)
if (admin.tableExists(tableNameObj)) {
val table = conn.getTable(tableNameObj)
table.put(puts)
table.close()
admin.close()
}
} catch {
case e: Exception =>
e.printStackTrace()
} def createTable(admin: Admin, tableName: String, colFamiles: Array[String]) = try {
val tableNameObj = TableName.valueOf(tableName)
if (!admin.tableExists(TableName.valueOf(tableName))) {
val desc = new HTableDescriptor(tableNameObj)
for (colFamily <- colFamiles) {
desc.addFamily(new HColumnDescriptor(colFamily))
}
admin.createTable(desc)
admin.close()
}
} catch {
case e: Exception =>
e.printStackTrace()
} def getPutList(): List[Put] = {
val random: Random = new Random
val putlist = new ArrayList[Put]();
for (i <- 0 until 100000) {
val rowkey: String = df2.format(random.nextInt(99)) + i
val put: Put = new Put(rowkey.getBytes)
put.add("cf".getBytes, "field".getBytes, "a".getBytes)
putlist.add(put)
}
putlist
} }
------------------------------------- 2)saveAsNewAPIHadoopDataset()接口
-------------------------------------
package cn.piesat.app import java.text.DecimalFormat import org.apache.hadoop.hbase.client._
import org.apache.hadoop.hbase.io.ImmutableBytesWritable
import org.apache.hadoop.hbase.mapreduce.TableOutputFormat
import org.apache.hadoop.hbase._
import org.apache.hadoop.mapred.JobConf
import org.apache.hadoop.mapreduce.Job
import org.apache.spark.sql.SparkSession import scala.collection.mutable.ListBuffer //10W用了2585ms
//100W用了13833ms、14880ms
object SparkToHbaseNewAPI {
val tableName = "test01"
val cf = "cf"
val num=1000000
val df2 = new DecimalFormat("00000000")
def main(args: Array[String]) = {
val sc = getSparkSession().sparkContext
val hbaseConf = HBaseConfiguration.create()
hbaseConf.set(HConstants.ZOOKEEPER_QUORUM, "hadoop01:2181")
val hbaseConn = ConnectionFactory.createConnection(hbaseConf)
val admin = hbaseConn.getAdmin
val jobConf = new JobConf(hbaseConf, this.getClass)
// 设置表名
jobConf.set(TableOutputFormat.OUTPUT_TABLE, tableName) // 如果表不存在则创建表
if (!admin.tableExists(TableName.valueOf(tableName))) {
val desc = new HTableDescriptor(TableName.valueOf(tableName))
val hcd = new HColumnDescriptor(cf)
desc.addFamily(hcd)
admin.createTable(desc)
} val job = Job.getInstance(jobConf)
job.setOutputKeyClass(classOf[ImmutableBytesWritable])
job.setOutputValueClass(classOf[Put])
job.setOutputFormatClass(classOf[TableOutputFormat[ImmutableBytesWritable]])
var list = ListBuffer[Put]()
println("数据准备中。。。。")
for (i <- 0 to num) {
val put = new Put(df2.format(i).getBytes())
put.addColumn(cf.getBytes(), "field".getBytes(), "abc".getBytes())
list.append(put)
}
println("数据准备完成!")
val data = sc.makeRDD(list.toList).map(x => {
(new ImmutableBytesWritable, x)
})
val start = System.currentTimeMillis() data.saveAsNewAPIHadoopDataset(job.getConfiguration)
val end = System.currentTimeMillis()
println("入库用时:" + (end - start))
sc.stop() } def getSparkSession(): SparkSession = {
SparkSession.builder().
appName("SparkToHbase").
master("local[4]").
config("spark.serializer", "org.apache.spark.serializer.KryoSerializer").
getOrCreate()
}
}
-------------------------------------
3)saveAsHadoopDataset()接口
-------------------------------------
package cn.piesat.app
import java.text.DecimalFormat import org.apache.hadoop.hbase._
import org.apache.hadoop.hbase.client.{ConnectionFactory, Put}
import org.apache.hadoop.hbase.io.ImmutableBytesWritable
import org.apache.hadoop.hbase.mapred.TableOutputFormat
import org.apache.hadoop.mapred.JobConf
import org.apache.spark.sql.SparkSession import scala.collection.mutable.ListBuffer
object SparkToHbaseOldAPI {
val tableName="test01"
val cf="cf"
val df2 = new DecimalFormat("00000000")
val num=1000000
//10W用时2623ms、2596ms
//100W用时14929ms、13753ms
def main(args: Array[String]): Unit = {
val sc = getSparkSession().sparkContext
val hbaseConf = HBaseConfiguration.create()
hbaseConf.set(HConstants.ZOOKEEPER_QUORUM, "hadoop01:2181")
val hbaseConn = ConnectionFactory.createConnection(hbaseConf)
val admin = hbaseConn.getAdmin
val jobConf = new JobConf(hbaseConf, this.getClass)
// 设置表名
jobConf.set(TableOutputFormat.OUTPUT_TABLE, tableName)
jobConf.setOutputFormat(classOf[TableOutputFormat]) // 如果表不存在则创建表
if (!admin.tableExists(TableName.valueOf(tableName))) {
val desc = new HTableDescriptor(TableName.valueOf(tableName))
val hcd = new HColumnDescriptor(cf)
desc.addFamily(hcd)
admin.createTable(desc)
} var list = ListBuffer[Put]()
println("数据准备中。。。。")
for (i <- 0 to num) {
val put = new Put(df2.format(i).getBytes())
put.addColumn(cf.getBytes(), "field".getBytes(), "abc".getBytes())
list.append(put)
}
println("数据准备完成!")
val data = sc.makeRDD(list.toList).map(x => {
(new ImmutableBytesWritable, x)
})
val start=System.currentTimeMillis()
data.saveAsHadoopDataset(jobConf)
val end=System.currentTimeMillis()
println("入库用时:"+(end-start))
sc.stop()
} def getSparkSession(): SparkSession = {
SparkSession.builder().
appName("SparkToHbase").
master("local[4]").
config("spark.serializer", "org.apache.spark.serializer.KryoSerializer").
getOrCreate()
}
}
-------------------------------------
4)BulkLoad方法(需要事先准备好数据文件)
------------------------------------
package cn.piesat import org.apache.hadoop.fs.Path
import org.apache.hadoop.hbase.client.{HTable, Table, _}
import org.apache.hadoop.hbase.io.ImmutableBytesWritable
import org.apache.hadoop.hbase.mapreduce.{HFileOutputFormat2, LoadIncrementalHFiles}
import org.apache.hadoop.hbase.util.Bytes
import org.apache.hadoop.hbase.{HBaseConfiguration, KeyValue, TableName}
import org.apache.hadoop.mapreduce.Job
import org.apache.spark.{SparkConf, SparkContext} object SparkHbaseBulkload { def main(args: Array[String]) = {
val sc = new SparkContext("local[4]", "appName")
val columnFamily1 = "cf"
val conf = HBaseConfiguration.create()
conf.set("hbase.zookeeper.property.clientPort", "2181")
conf.set("hbase.zookeeper.quorum", "hadoop01") val source=sc.textFile("file:///E:/student.txt").map{
x=>{
val splited=x.split(",")
val rowkey=splited(0)
val cf=splited(1)
val clomn=splited(2)
val value=splited(3)
(rowkey,cf,clomn,value)
}
}
val rdd = source.map(x => {
//将rdd转换成HFile需要的格式,我们上面定义了Hfile的key是ImmutableBytesWritable,那么我们定义的RDD也是要以ImmutableBytesWritable的实例为key
//KeyValue的实例为value
//rowkey
val rowKey = x._1
val family = x._2
val colum = x._3
val value = x._4
(new ImmutableBytesWritable(Bytes.toBytes(rowKey)), new KeyValue(Bytes.toBytes(rowKey), Bytes.toBytes(family), Bytes.toBytes(colum), Bytes.toBytes(value)))
})
//生成的HFile的临时保存路径
val stagingFolder = "hdfs://hadoop01:9000/data12"
//将日志保存到指定目录
rdd.saveAsNewAPIHadoopFile(stagingFolder,
classOf[ImmutableBytesWritable],
classOf[KeyValue],
classOf[HFileOutputFormat2],
conf)
//此处运行完成之后,在stagingFolder会有我们生成的Hfile文件 //开始即那个HFile导入到Hbase,此处都是hbase的api操作
val load = new LoadIncrementalHFiles(conf)
//hbase的表名
val tableName = "output_table"
//创建hbase的链接,利用默认的配置文件,实际上读取的hbase的master地址
val conn = ConnectionFactory.createConnection(conf)
//根据表名获取表
val table: Table = conn.getTable(TableName.valueOf(tableName))
try {
//创建一个hadoop的mapreduce的job
val job = Job.getInstance(conf)
//设置job名称
job.setJobName("DumpFile")
//此处最重要,需要设置文件输出的key,因为我们要生成HFil,所以outkey要用ImmutableBytesWritable
job.setMapOutputKeyClass(classOf[ImmutableBytesWritable])
//输出文件的内容KeyValue
job.setMapOutputValueClass(classOf[KeyValue])
//配置HFileOutputFormat2的信息
HFileOutputFormat2.configureIncrementalLoadMap(job, table)
//开始导入
val start=System.currentTimeMillis()
load.doBulkLoad(new Path(stagingFolder), table.asInstanceOf[HTable])
val end=System.currentTimeMillis()
println("用时:"+(end-start)+"毫秒!")
} finally {
table.close()
conn.close()
}
}
}
------------------------------------
Spark入Hbase的四种方式效率对比的更多相关文章
- Spark读写Hbase的二种方式对比
作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 一.传统方式 这种方式就是常用的TableInputFormat和TableOutputForm ...
- 判断字符串中是否存在的几种方案:string.indexof、string.contains、list.contains、list.any几种方式效率对比
我们在做项目时,可能会遇到这样的需求,比如判断,1,2,3,33,22,123, 中是否存在,3,. var str=",1,2,3,33,22,123,"; 一般有几种方式: 1 ...
- Spark JDBC系列--取数的四种方式
Spark JDBC系列--取数的四种方式 一.单分区模式 二.指定Long型column字段的分区模式 三.高自由度的分区模式 四.自定义option参数模式 五.JDBC To Other Dat ...
- Spark:DataFrame批量导入Hbase的两种方式(HFile、Hive)
Spark处理后的结果数据resultDataFrame可以有多种存储介质,比较常见是存储为文件.关系型数据库,非关系行数据库. 各种方式有各自的特点,对于海量数据而言,如果想要达到实时查询的目的,使 ...
- 160624、Spark读取数据库(Mysql)的四种方式讲解
目前Spark支持四种方式从数据库中读取数据,这里以Mysql为例进行介绍. 一.不指定查询条件 这个方式链接MySql的函数原型是: 1 def jdbc(url: String, table: S ...
- java 20 -10 字节流四种方式复制mp3文件,测试效率
电脑太渣,好慢..反正速率是: 高效字节流一次读写一个字节数组 > 基本字节流一次读写一个字节数组 > 高效字节流一次读写一个字节 > 基本字节流一次读写一个字节 前两个远远快过后面 ...
- C#批量插入数据到Sqlserver中的四种方式
我的新书ASP.NET MVC企业级实战预计明年2月份出版,感谢大家关注! 本篇,我将来讲解一下在Sqlserver中批量插入数据. 先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的 ...
- 【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
不考虑第三方框架,如果只使用JDK提供的API,那么可以使用三种方式调用WebService服务:另外还可以使用Ajax调用WebService服务. 预备工作:开启WebService服务,使用jd ...
- C#_批量插入数据到Sqlserver中的四种方式
先创建一个用来测试的数据库和表,为了让插入数据更快,表中主键采用的是GUID,表中没有创建任何索引.GUID必然是比自增长要快的,因为你生成一个GUID算法所花的时间肯定比你从数据表中重新查询上一条记 ...
随机推荐
- 【Ansible】记一次技术博客害死人的经历——ansible模板变量注入探究
风和日丽,夏天的北京湿热并举,睁不开的眼睛里,横竖都看着是“吃人”. 带薪学习的日子不好过,要在几天内迅速掌握导师下发要求学习的技能,看着以前一起蹲IT坑的同事人来人往,用隔壁同性黄同学的话来说,就是 ...
- 西安邀请赛-L(打表找规律)
题目链接:https://nanti.jisuanke.com/t/39279 题意:给定n个不同的数表示的序列,定义两种操作:1. 交换前一半和后一半(如果有奇数个,则中间的不管).2. 交换每个偶 ...
- windows 装mac
必备条件: 1.vmware虚拟机 2.给相应版本虚拟机打mac补丁 3.用securable检测CPU支持虚拟化设置 4.mac镜像文件 5.这时候还不能启动虚拟机,还需要在引导文件里面进行参数修改 ...
- python实现:递归删除文件并保存删除记录
说明: 此脚本用于删除指定目录及子目录下符合删除规则的文件,并将删除的文件记录到指定目录下的指定文件,便于查看删除记录. 注意: 此脚本删除的文件,不会进入回收站,将被直接彻底删除,请谨慎操作!!! ...
- 2018.08.15【2018提高组】模拟A组 比赛总结
总结 T1 这题我一看,哇!好简单啊! 直接建立每一个字母的映射就可以了. 我很快就打完了程序,跳到下一题. 等到比赛快结束时,我才发现了一个可怕的数据: 1 abcdefghijklmnopqrst ...
- python网络编程-socket套接字通信循环-粘包问题-struct模块-02
前置知识 不同计算机程序之间数据的传输 应用程序中的数据都是从程序所在计算机内存中读取的. 内存中的数据是从硬盘读取或者网络传输过来的 不同计算机程序数据传输需要经过七层协议物理连接介质才能到达目标程 ...
- 一般处理程序,ajax
一般处理程序调用session: 在.aspx.cs页中读写Session都是Session["***"]就可以获取或者写入.但是在一般处理程序也就是ashx页面中,再这样写的话, ...
- LOJ题解#136. 最小瓶颈路 DFS+Kruskal
题目链接: https://loj.ac/problem/136 思路: 在我的这篇博客中已经讲到什么是最短瓶颈路,同时给出了一个用Kruskal求最短瓶颈路的一个简洁易懂的方法,然而这道题目可以看作 ...
- React前端有钱途吗?《React+Redux前端开发实战》学起来
再不学React就真的跟不上大前端的形式了,目前几乎所有前端的招聘条件都是精通React者优先,看看拉勾网的React薪资,都是15K-20K,这个暑假,必须动起来了. 如果你熟悉JavaScript ...
- 服务命令(systemctl的使用)
常用的service与systemctl命令的对比 应用举例: ●start:开启服务 ●stop:停止服务 ●status:参数来查看服务运行情况 ●restart:重新加载服务 应用举例·: #启 ...