今天去面试了一波,因为调度系统采用了SparkSql实现数据从Mysql到hive,在这一点上面试官很明显很不满我对于Spark的理解,19年的第一个面试就这么挂了。

有问题不怕,怕的是知道了问题还得过且过。现在就来梳理下我的项目是怎么使用Spark导数的

第一步:把mysql中的表放入内存

  1. properties.put("user", dbUser);
  2. properties.put("password", dbPassword);
  3. properties.put("driver", dbDriver);
  4. Dataset<Row> bizdateDS = sparkSession.read().jdbc(
  5. dbUrl,
  6. dbTableName,
  7. properties
  8. );

其中:org.apache.spark.sql.Dataset(这里面试官问我怎么把mysql的数据转化到Spark,我没答上来)

第二步:创建数据库与表

2.1 创建库

  1. String createDBSQL = "CREATE DATABASE IF NOT EXISTS " + hiveDBName + " LOCATION '" + dbPath + "'";
  2. sparkSession.sql(createDBSQL);
  3. ```
  4. 2.2创建表
  5. 分成两步,第一步读取Mysql元数据字段,第二步把这些字段创建出来
  6. 2.2.1 读取mysql字段
  1. StructType structType = bizdateDS.schema();
  2. StructField[] structFields = structType.fields();
  3. /*
  4. structField是StructType中的字段。
  5. param:name此字段的名称。
  6. param:dataType此字段的数据类型。
  7. param:nullable指示此字段的值是否为空值。
  8. param:metadata此字段的元数据。 如果未修改列的内容(例如,在选择中),则应在转换期间保留元数据。
  9. */

  1. 2.2.2 创建字段
  1. String sourceType; //Name of the type used in JSON serialization.
  2. String columnName;
  3. String targetType;
  4. StructField structField;
  5. SparkDataTypeEnum sparkDataType;
  6. StringBuilder createBuilder = new StringBuilder(capacity);
  7. createBuilder.append("CREATE TABLE IF NOT EXISTS ").append(realHiveTableName).append(" (");
  8. List<String> dbTableColumns = Lists.newArrayList();
  9. Map<String, String> dbTableColumnTypeMap = Maps.newHashMap();
  10. //把Mysql中的每个字段都提取出来
  11. for (int i = 0, len = structFields.length; i < len; i++) {
  12. structField = structFields[i];
  13. sourceType = structField.dataType().typeName();
  14. columnName = structField.name();
  15. if (sourceType.contains("(")) { //处理类似varchar(20)
  16. sourceType = sourceType.substring(0, sourceType.indexOf("("));
  17. }
  18. sparkDataType = SparkDataTypeEnum.getItemByType(sourceType);
  19. if (null != sparkDataType) {
  20. targetType = sparkDataType.getHiveDataType().getType();
  21. //时间戳字段强转成string字段
  22. if(targetType.equals("timestamps")) targetType.equals("string");
  23. } else {
  24. targetType = HiveDataTypeEnum.STRING.getType();
  25. }
  26. dbTableColumns.add(columnName);
  27. dbTableColumnTypeMap.put(columnName, targetType);
  28. if (i != 0) {
  29. createBuilder.append(",");
  30. }
  31. createBuilder.append(columnName).append(" ").append(targetType);
  32. }
  33. createBuilder.append(") PARTITIONED by (").append(partitionColumn)
  34. .append(" STRING) ");
  35. sparkSession.sql(createTableSQL);

  1. 2.3 对比字段
  2. 我们在2.2中,如果hive有字段了,那么就不会创建表。
  3. 问题在于,如果hive中的字段比mysql中的少怎么办?
  4. 2.3.1 获取hive中的表字段
  1. HiveUtil connectionToHive = new HiveUtil("org.apache.hive.jdbc.HiveDriver", hiveUrl, hiveUser, hivePassword);
  2. public List<String> getTableColumns(String dbName,String tableName) throws SQLException {
  3. ResultSet rs = null;
  4. try {
  5. if (!this.validateTableExist(tableName)) {
  6. return null;
  7. }
  8. DatabaseMetaData metaData = connection.getMetaData();
  9. rs = metaData.getColumns(null, dbName, tableName.toUpperCase(), "%");
  10. List<String> columns = new ArrayList();
  11. while (rs.next()) {
  12. columns.add(rs.getString("COLUMN_NAME").toLowerCase());
  13. }
  14. return columns;
  15. } catch (SQLException e) {
  16. throw e;
  17. } finally {
  18. if (null != rs) {
  19. rs.close();
  20. }
  21. }
  22. }

  1. 2.3.2 对比字段并且添加:
  1. for (String dbTableColumn : dbTableColumns) {
  2. if (StringUtil.hasCapital(dbTableColumn)) {
  3. DingDingAlert.sendMsg(dbTableName + "的" + dbTableColumn + "是大写字段,替换成小写");
  4. logger.warn(dbTableName + "的" + dbTableColumn + "是大写的,把他替换成小写");
  5. sb.append("\n " + GetTime.getTimeStamp("yyyy-MM-dd HH:mm:ss") + "| WARN |" + "表" + hiveTableName + "在hive中不存在,程序关闭");
  6. dbTableColumn = StringUtil.convertStringToLowerCase(dbTableColumn, false);
  7. }
  8. if (!hiveTableColumns.contains(dbTableColumn)) {
  9. alterColumns.add(dbTableColumn);
  10. }
  11. }

  1. 2.4 将内存中的表存入hive
  1. bizdateDS.createOrReplaceTempView(tmpTableName); //注意这里不是直接从mysql抽到hive,而是先从Mysql抽到内存中
  2. insert hive_table select hive中的已经有的表的字段 from tmpTableName

  1. ##很明显的,如果不是需要和hive已经有的表交互根本用不到jdbc

SparkSql实现Mysql到hive的数据流动的更多相关文章

  1. 从MySQL到Hive,数据迁移就这么简单

    使用Sqoop能够极大简化MySQL数据迁移至Hive之流程,并降低Hadoop处理分析任务时的难度. 先决条件:安装并运行有Sqoop与Hive的Hadoop环境.为了加快处理速度,我们还将使用Cl ...

  2. 使用Sqoop从mysql向hdfs或者hive导入数据时出现的一些错误

    1.原表没有设置主键,出现错误提示: ERROR tool.ImportTool: Error during import: No primary key could be found for tab ...

  3. Spark操作MySQL,Hive并写入MySQL数据库

    最近一个项目,需要操作近70亿数据进行统计分析.如果存入MySQL,很难读取如此大的数据,即使使用搜索引擎,也是非常慢.经过调研决定借助我们公司大数据平台结合Spark技术完成这么大数据量的统计分析. ...

  4. 从hive将数据导出到mysql(转)

    从hive将数据导出到mysql http://abloz.com 2012.7.20 author:周海汉 在上一篇文章<用sqoop进行mysql和hdfs系统间的数据互导>中,提到s ...

  5. sqoop用法之mysql与hive数据导入导出

    目录 一. Sqoop介绍 二. Mysql 数据导入到 Hive 三. Hive数据导入到Mysql 四. mysql数据增量导入hive 1. 基于递增列Append导入 1). 创建hive表 ...

  6. Hive[4] 数据定义 HiveQL

    HiveQL 是 Hive 查询语言,它不完全遵守任一种 ANSI SQL 标准的修订版,但它与 MySQL 最接近,但还有显著的差异,Hive 不支持行级插入,更新和删除的操作,也不支持事务,但 H ...

  7. hadoop笔记之Hive的数据存储(视图)

    Hive的数据存储(视图) Hive的数据存储(视图) 视图(view) 视图是一种虚表,是一个逻辑概念:可以跨越多张表 既然视图是一种虚表,那么也就是说用操作表的方式也可以操作视图 但是视图是建立在 ...

  8. Sqoop使用,mysql,hbase,hive等相互转换

    Sqoop 是一款用来在不同数据存储软件之间进行数据传输的开源软件,它支持多种类型的数据储存软件. 安装 Sqoop 1.下载sqoop并加mysql驱动包 http://mirror.bit.edu ...

  9. 使用sqoop将MySQL数据库中的数据导入Hbase

    使用sqoop将MySQL数据库中的数据导入Hbase 前提:安装好 sqoop.hbase. 下载jbdc驱动:mysql-connector-java-5.1.10.jar 将 mysql-con ...

随机推荐

  1. 3YAdmin-专注通用权限控制与表单的后台管理系统模板

    3YAdmin基于React+Antd构建.GitHub搜索React+Antd+Admin出来的结果没有上百也有几十个,为什么还要写这个东西呢? 一个后台管理系统的核心我认为应该是权限控制,表单以及 ...

  2. jQuery 效果 - 停止动画

    jQuery 停止动画 jQuery stop() 方法用于在动画或效果完成前对它们进行停止. jQuery stop() 方法 jQuery stop() 方法用于停止动画或效果,在它们完成之前. ...

  3. WCF DEMO1 创建自托管宿主

    using System; using System.ServiceModel; using System.ServiceModel.Channels; //注意:需要引用程序集 System.Ser ...

  4. saas模式

    SaaS是Software-as-a-service(软件即服务).SaaS提供商为企业搭建信息化所需要的所有网络基础设施及软件.硬件运作平台,并负责所有前期的实施.后期的维护等一系列服务,企业无需购 ...

  5. Winfrom 基于TCP的Socket服务端 多线程(进阶版)

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. C# 的逻辑运算

    &.^.!和|操作符称为逻辑操作符,用逻辑操作符把运算对象连接起来符合C#语法的式子称为逻辑表达式.逻辑 操作符“!”和“^”只作用于其后的操作数,故称为一元操作符.而“&&” ...

  7. Java基础教程(17)--接口

      就像类一样,接口也是引用类型.它可以包含常量,方法签名,默认方法,静态方法和嵌套类型.在接口中,只有默认方法和静态方法有方法体.但不同于类,接口无法实例化,它只能被类实现或被其他接口继承. 一.定 ...

  8. java实现黑客帝国数字雨特效(转)

    原文出处https://www.cnblogs.com/x110/p/4239585.html 我在原文的基础上做了优化,使动画看起来更流畅,效果如下 import java.awt.*; impor ...

  9. ef和mysql使用(二)--让mysql支持EntityFramework.Extended实现批量更新和删除

    我们都知道Entity Framework 中不能同时更新多条记录,但是一个老外写的扩展库可以实现此功能EntityFramework.Extended,但是如何是mysql数据库要怎么实现呢 首先实 ...

  10. 深入浅出图解【计算机网络】 之 【TCP可靠传输的实现2: 超时重传+拥塞控制】

    [前言]上一篇文章介绍了关于TCP的基础知识,以及建立(释放)连接和滑动窗口的概念. 本篇文章将延续上一篇的思路,继续介绍TCP实现可靠传输的机制. 超时重传 上一篇文章里介绍过TCP采用停止等待协议 ...