转载自:https://www.jianshu.com/p/e4c90dc08935

1、需求背景

通过Spark将关系型数据库(以Oracle为例)的表同步的Hive表,要求用Spark建表,有字段注释的也要加上注释。Spark建表,有两种方法:

  • 用Spark Sql,在程序里组建表语句,然后用Spark.sql("建表语句")建表,这种方法麻烦的地方在于你要读取Oracle表的详细的表结构信息,且要进行Oracle和Hive的字段类型进行一一对应
  • 用DataFrame 的saveAsTable方法,这种方法如果对应的数据库里没有表,则Spark会根据DataFrame的schema自动建表,比较简单,不用考虑字段类型匹配转化问题,但是这种方法有一个问题,Spark读取Oracle的表为DataFrame时,并不能将表字段的注释读进来,所以就有了如标题所示的需求。(一开始以为DataFrame不能加注释,经过研究,发现是可以的!)

2、如何查看DataFrame是否有注释

前面讲到DataFrame里没有Oracle的注释信息,但是如果数据源为Hive的话,是可以将注释获取到的。

2.1 新建Hive测试表(带注释)

create table `test` (
`id` string comment 'ID',
`Name` string comment '名字'
)
comment '测试';

2.2 Spark读取hive表并打印注释(在spark-shell里执行)

首先看一下df.printSchema里并没有注释信息

sql("use test")
val df = spark.table("test")
df.printSchema
root
|-- id: string (nullable = true)
|-- name: string (nullable = true)

用下面这行代码便可以打印注释信息:

df.schema.foreach(s=>println(s.name,s.metadata))
(id,{"comment":"ID","HIVE_TYPE_STRING":"string"})
(name,{"comment":"名字","HIVE_TYPE_STRING":"string"})

3、读取Oracle表并打印DataFrmae的元数据信息

3.1 新建Oracle测试表(带注释)

CREATE TABLE ORA_TEST (
ID VARCHAR2(),
NAME VARCHAR2()
);
COMMENT ON COLUMN ORA_TEST.ID IS 'ID';
COMMENT ON COLUMN ORA_TEST.NAME IS '名字';
COMMENT ON TABLE ORA_TEST IS '测试';
  • 注:上面的注释语句和建表语句需要分开执行,或者也可以在数据库工具执行脚本,比如我用的DBeaver用快捷键Alt+x即可。当然也可以在工具的界面直接建表均可。

3.2 读取Oracle表,并打印元数据

代码:

package com.dkl.leanring.spark.sql.Oracle

import org.apache.spark.sql.SparkSession

object OracleSchemaDemo {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("OracleSchemaDemo").master("local").getOrCreate()
val df = spark.read
.format("jdbc")
.option("url", "jdbc:oracle:thin:@192.168.44.128:1521:orcl")
.option("dbtable", "ORA_TEST")
.option("user", "bigdata")
.option("password", "bigdata")
.option("driver", "oracle.jdbc.driver.OracleDriver")
.load()
df.schema.foreach(s => println(s.name, s.metadata)) spark.stop }
}
(ID,{"name":"ID","scale":})
(NAME,{"name":"NAME","scale":})

注:Spark2.3.0和Spark2.2.1的元数据不太一样,上面的结果是Spark2.2.1(也是我写博客测试用的),项目中用的Spark2.3.0,2.3.0的元数据是空的,如下

(ID,{})
(NAME,{})

可见并没有注释信息

3.3 给DataFrame添加注释

import org.apache.spark.sql.types._
val commentMap = Map("ID" -> "ID", "NAME" -> "名字") val schema = df.schema.map(s => {
s.withComment(commentMap(s.name))
}) //根据添加了注释的schema,新建DataFrame
val new_df = spark.createDataFrame(df.rdd, StructType(schema)).repartition() new_df.schema.foreach(s => println(s.name, s.metadata))
(ID,{"comment":"ID","name":"ID","scale":})
(NAME,{"comment":"名字","name":"NAME","scale":})

4、 测试写到Hive表有没有注释

需将前面代码中的spark改为支持hive,即加上enableHiveSupport()

spark.sql("use test")
new_df.write.mode("overwrite").saveAsTable("ORA_TEST")

然后在hive里看一下,是否有注释

可以看到,成功的把注释也保存到里hive里

5、附录

附上在Eclipse运行的完整代码

package com.dkl.leanring.spark.sql.Oracle

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.types._ object OracleSchemaDemo {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("OracleSchemaDemo").master("local").enableHiveSupport().getOrCreate()
val df = spark.read
.format("jdbc")
.option("url", "jdbc:oracle:thin:@192.168.44.128:1521:orcl")
.option("dbtable", "ORA_TEST")
.option("user", "bigdata")
.option("password", "bigdata")
.option("driver", "oracle.jdbc.driver.OracleDriver")
.load()
df.schema.foreach(s => println(s.name, s.metadata)) val commentMap = Map("ID" -> "ID", "NAME" -> "名字") val schema = df.schema.map(s => {
s.withComment(commentMap(s.name))
}) //根据添加了注释的schema,新建DataFrame
val new_df = spark.createDataFrame(df.rdd, StructType(schema)).repartition() new_df.schema.foreach(s => println(s.name, s.metadata)) spark.sql("use test")
//保存到hive
new_df.write.mode("overwrite").saveAsTable("ORA_TEST") spark.stop }
}

Spark通过修改DataFrame的schema给表字段添加注释(转载)的更多相关文章

  1. mysql 数据库 表字段添加表情兼容

    项目中的几个需要支持Emoji表情符号,手机自带的表情,其实添加也很简单: 1 修改数据库 配置my.cnf  init-connect='SET NAMES utf8mb4'             ...

  2. oracle 表字段添加 修改 删除语法

    修改列名 alter table 表明 rename column rename 老列名 to 新列名添加 字段alter table 表名 add(字段名 类型):删除字段alter table 表 ...

  3. PowerDesigner15.1给自定义架构表字段添加MS_Description出错

    原因:系统函数sp_addextendedproperty 的第3个参数(用户名) 应该是Schema.但PD在生成的时候却是’user’ 解决方法 在PDM时.DataBase >> E ...

  4. Maven插件mybatis-generator,如何让生成的PO类的field上有对应表字段的注释

    前言 去年刚入职的时候,我就发现,po类(和数据库表对应的类)上,一片都是光秃秃的,什么注释都没有,类上没注释,field上也没注释. 在以前的项目中,其实我们都是有生成注释的,比如,对于下面这个表: ...

  5. @MySQL为表字段添加索引

    删除索引~ DROP INDEX `idx_dict_type` ON `article` 1.添加PRIMARY KEY(主键索引): ALTER TABLE `table_name` ADD PR ...

  6. Mysql如何为表字段添加索引???

    1.添加PRIMARY KEY(主键索引): ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 2.添加UNIQUE(唯一索引) : ALTE ...

  7. Mysql优化-为表字段添加索引

    1.添加PRIMARY KEY(主键索引): ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 2.添加UNIQUE(唯一索引) : ALTE ...

  8. ORACLE修改表字段顺序

    1.若'GYZL_BZPWL_TB' 为要修改的表名,注意表名一定要大写!此句可以获取表的id.select object_id from all_objects where object_name= ...

  9. oracle查看表名称和表字段注释

    --查询该表字段的注释select * from user_col_comments where Table_Name like '%SMS%' --查询类似表select * from user_t ...

随机推荐

  1. c++的动态绑定和静态绑定及多态的实现原理(摘)

    C++多态的实现原理 为了支持c++的多态性,才用了动态绑定和静态绑定.理解它们的区别有助于更好的理解多态性,以及在编程的过程中避免犯错误. 需要理解四个名词:对象的静态类型:对象在声明时采用的类型. ...

  2. Attention Model详解

    要是关注深度学习在自然语言处理方面的研究进展,我相信你一定听说过Attention Model(后文有时会简称AM模型)这个词.AM模型应该说是过去一年来NLP领域中的重要进展之一,在很多场景被证明有 ...

  3. 使用Navicat Premium 12导出SQL语句并在Power Designer 16.5中生成物理模型

    内容简介 本文主要介绍使用Navicat Premium 12导出建表SQL(使用MySQL数据库)文件,并在Power Designer 16.5中使用导出的SQL文件来生成物理模型的步骤. 操作步 ...

  4. Djiango权限组件

    一. login中注册 权限url def login(request): if request.method == "POST": username = request.POST ...

  5. 【贪心】Moving Tables POJ 1083

    题目链接:http://poj.org/problem?id=1083 题目大意:走廊上的房间如下图设置,现在有n个移动桌子的任务,把桌子从xi移动到yi(整个过程中会占用xi到yi房间之间的走廊), ...

  6. thrift 安装

    1.下载 去官网 https://thrift.apache.org/download 下载两个文件,下载地址 http://archive.apache.org/dist/thrift/0.9.3/ ...

  7. LightOJ - 1058 - Parallelogram Counting(数学,计算几何)

    链接: https://vjudge.net/problem/LightOJ-1058 题意: There are n distinct points in the plane, given by t ...

  8. 谈MongoDB的应用场景

    转载自:http://blog.csdn.net/adparking/article/details/38727911 MongoDB的应用场景在网上搜索了下,很少介绍关于传统的信息化应用中如何使用M ...

  9. YAML_17 Playbook 综合

    Playbook1.语法特性如下:(1)"---"首行顶格开始(2)#号注释(3)缩进统一,不同的缩进代表不同的级别,缩进要对齐,空格和tab不能混用(4)区别大小写,键值对k/v ...

  10. vue组件传值的三种方式,文字版解释

    父传子: 当子组件子父组件中当标签使用的时候,给子组件添加一个自定义属性,值为需要传递的值(如: <Child v-bind:parentToChild="parentMsg" ...