Spark-SQL的Java实践案例(五)
本章核心:JDBC 连接外部数据库,sparkSQL优化,故障监测
史上最简单的spark教程
所有代码示例地址:https://github.com/Mydreamandreality/sparkResearch
(提前声明:文章由作者:张耀峰 结合自己生产中的使用经验整理,最终形成简单易懂的文章,写作不易,转载请注明)
(文章参考:Elasticsearch权威指南,Spark快速大数据分析文档,Elasticsearch官方文档,实际项目中的应用场景)
(帮到到您请点点关注,文章持续更新中!)
Git主页 https://github.com/Mydreamandreality
在这里我们继续之前的SparkSQL的案例啊,没有看上一章节的兄弟萌 点击这里哈https://blog.csdn.net/youbitch1/article/details/88852644
装逼开始:[狗头保命]
ps:这应该是sparkSql的最后一章节了
- Spark还支持使用JDBC从其他的数据库读取数据的数据源,返回的结果是dataframe
- 如何使用
- 使用DataSourceApi将来自远程数据库的表作为dataframe或者sparkSQL的临时视图进行加载
- 用户可以在数据源中指定JDBC连接属性
- 连接属性如下:
属性说明只是简单的说明,具体看后续的代码案例
属性参数 | 属性说明 |
---|---|
URL | JDBC的URL,这个我们搞java开发的应该都知道 |
user | 数据库用户名 |
password | 数据库密码 |
dbtable | 表名称 |
driver | jdbc driver |
partitioncolumn,lowerbound,upperbound | 指定分区的大小 |
numPartitions | 表读写的并行度最大分区数,也是并发JDBC的最大连接数 |
fetchsize | JDBC抓取大小,用于确定数据每次往返传递的行数,默认值较小(一般为10),适用于读取操作 |
batchsize | JDBC批处理的大小,用于确定数据每次往返传递的行数,有利于提升jdbcdriver的性能默认1000,只适用于写操作 |
isolationlevel | 事务隔离级别,适用于写操作 |
truncate | 此选项会导致Spark截断现有表,而不是删除并重新创建 |
createtableoptions | 创建表时指定各种选项,比如 CREATE TABLE t (name string) ENGINE=InnoDB |
createtablecolumntypes | 使用数据库的数据类型,而不是sparkSQL的默认类型,适用于写操作 |
老规矩,理论BB完了,下面就是我们的代码案例
读取JDBC数据代码案例:
//第一种方式
Dataset<Row> rddDataset = sparkSession.read().format("jdbc")
.option("url","jdbc:mysql:dbserver")
.option("user","root")
.option("password","root")
.option("dbtable","sys_alarm")
.load();
//创建的第二种方式
Properties properties = new Properties();
properties.put("user","root");
properties.put("password","root");
Dataset<Row> rowDataset = sparkSession.read().jdbc("jdbc:mysql:dbserver","sys_alarm",properties);
可以看到第二种创建方法 .jdbc()的有参方法,参数已经帮我们定义好了
源码解析如下:
在此处也有各个参数的详解以及需要注意的事项
写入JDBC数据代码案例
- 其实写入和读取基本都差不太多,看下面的案例
//数据保存到JDBC源
rddDataset.write().format("jdbc")
.option("url","jdbc:mysql:dbserver")
.option("user","root")
.option("password","root")
.option("dbtable","sys_alarm")
.save();
//第二种方式把数据保存到JDBC源
rddDataset.write()
.jdbc("jdbc:mysql:dbserver","sys_alarm",properties);
//第三种方式:指定写的时候创建表列的数据类型
rddDataset.write()
.option("createTableColumnTypes", "name CHAR(64), comments VARCHAR(1024)")
.jdbc("jdbc:mysql:dbserver","sys_alarm",properties);
- 还是指定一些必须的参数,第三个中指定数据类型
- 还是相对比较简单的
- 大家在做的过程中可以没事看看源码,加深理解,很多的概念在源码中已经写得很清楚了
故障排除(摘自:官方文档)
- 在客户端会话(client session)中或者所有 executor 上,JDBC 驱动类必须可见于原生的类加载器。
- 这是因为 Java 的驱动管理(DriverManager )类在打开一个连接之前会做一个安全检查,这就导致它忽略了所有对原生类加载器不可见的驱动
- 一个方便的方法,就是修改所有 worker 节点上的 compute_classpath.sh 以包含你的驱动 Jar 包
性能调优
- 之前说sparkSQL会自动帮我们调优,但是我们还是可以在此基础上优化的
- 不过调优嘛,从代码层面说要么就是缓存,要么就是调整初始选项
第一种调优方式:缓存数据到内存
- SparkSQL可以通过cacheTable("tableName)或者dataFrame.cache()以列式存储的方式缓存表到内存中
- 之后的话,sparkSQL会扫描必要的列,并且自动调整压缩的比例,以此减少GC和内存的压力
- 我们可以用 spark.uncacheTable("tablename)删除内存中的表
第二种调优方式:调整初始选项
- 下面的选项可以提升sparkSQL的查询能力,不过spark每次更新都会自动执行很多的优化操作,这些选项可能在以后就不需要我们手动调节优化了
参数名称 | 默认值 | 含义 |
---|---|---|
spark.sql.files.maxPartitionBytes | 134217728 (128 MB) | 读取文件时单个分区可容纳的最大字节数 |
spark.sql.files.openCostInBytes | 4194304 (4 MB) | 打开文件的估算成本,按照同一时间能够扫描的字节数来测量。当往一个分区写入多个文件的时候会使用。高估更好, 这样的话小文件分区将比大文件分区更快 (先被调度) |
spark.sql.autoBroadcastJoinThreshold | 10485760 (10 MB) | 配置一个表在执行 join 操作时能够广播给所有 worker 节点的最大字节大小。通过将这个值设置为-1,可以禁用广播 |
spark.sql.shuffle.partitions | 200 | 配置为连接或聚合操作混洗(shuffle)数据时使用的分区数 |
Spark-SQL JavaApi案例总结
- 兄弟萌,到目前为止,我们已经学会了用spark的spark-SQL组件处理结构化,半结构化的数据,包括调优技巧,外部JDBC的连接,数据读写等,已经可以进行基本的开发了,在开发中遇到问题可以源码阅读,或者留言我们一起交流学习!