离线数据处理——子任务一:数据抽取

目录

子任务一:数据抽取

实现代码

(1)定义工具类

(2)定义工作类


子任务一:数据抽取

编写Scala代码,使用Spark将MySQL的shtd_store库中表user_info、sku_info、base_province、base_region、order_info、order_detail的数据增量抽取到Hive的ods库中对应表user_info、sku_info、base_province、base_region、order_info、order_detail中。

1.抽取shtd_store库中user_info的增量数据进入Hive的ods库中表user_info。根据ods.user_info表中operate_time或create_time作为增量字段(即MySQL中每条数据取这两个时间中较大的那个时间作为增量字段去和ods里的这两个字段中较大的时间进行比较),只将新增的数据抽入,字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.user_info命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;

2.抽取shtd_store库中sku_info的增量数据进入Hive的ods库中表sku_info。根据ods.sku_info表中create_time作为增量字段,只将新增的数据抽入,字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.sku_info命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;

3.抽取shtd_store库中base_province的增量数据进入Hive的ods库中表base_province。根据ods.base_province表中id作为增量字段,只将新增的数据抽入,字段名称、类型不变并添加字段create_time取当前时间,同时添加静态分区,分区字段类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.base_province命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;

4.抽取shtd_store库中base_region的增量数据进入Hive的ods库中表base_region。根据ods.base_region表中id作为增量字段,只将新增的数据抽入,字段名称、类型不变并添加字段create_time取当前时间,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.base_region命令,将结果截图粘贴至对应报告中;

5.抽取shtd_store库中order_info的增量数据进入Hive的ods库中表order_info,根据ods.order_info表中operate_time或create_time作为增量字段(即MySQL中每条数据取这两个时间中较大的那个时间作为增量字段去和ods里的这两个字段中较大的时间进行比较),只将新增的数据抽入,字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.order_info命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下;

6.抽取shtd_store库中order_detail的增量数据进入Hive的ods库中表order_detail,根据ods.order_detail表中create_time作为增量字段,只将新增的数据抽入,字段名称、类型不变,同时添加静态分区,分区字段为etl_date,类型为String,且值为当前比赛日的前一天日期(分区字段格式为yyyyMMdd)。使用hive cli执行show partitions ods.order_detail命令,将结果截图粘贴至客户端桌面【Release\任务B提交结果.docx】中对应的任务序号下。

实现代码

(1)定义工具类

该工具类包含两个方法。loadJDBC方法负责加载mysql中的数据,appendHive方法负责将增量抽取的数据追加写入到hive的相关表中。

package com.hbzy.GZ03

import org.apache.orc.OrcProto.ColumnEncoding
import org.apache.spark.sql.{DataFrame, SparkSession}

// 负责mysql的链接和hive的写入
object gz03utils {

  // 加载jdbc
  def loadJDBC(sparkSession: SparkSession, jdbcMap:Map[String, String]):DataFrame ={

    val dataframe: DataFrame = sparkSession.read.format("jdbc").options(jdbcMap).load()

    dataframe

  }

  // 增量写入hive
  def appendHive(sparkSession: SparkSession, dataFrame: DataFrame, hiveMap:Map[String, String]):Unit = {
    val db = hiveMap("db")  // 确定数据库
    val tb = hiveMap("tb")  // 确定表
    val partitionColumn = hiveMap.get("partitionColumn")  // 确定分区列

    sparkSession.sql(s"use ${db}")    // 使用插值法填充

    // 有的表需要分区,有的不需要。这里使用模式匹配来分别处理
    partitionColumn match {
      case Some(column) => dataFrame
        .write
        .format("parquet")  // 这里的关键是写入格式问题,不能用hive,要用parquet
        .mode("append")
        .partitionBy(column)
        .saveAsTable(tb)
      case None => dataFrame
        .write
        .format("parquet")
        .mode("append")
        .saveAsTable(tb)
    }


  }

}

(2)定义工作类

本题需要增量抽取相同的数据库的6张不同的表到hive数据库中。所以定义了6个方法,分别对应了6张表的抽取。user_info、sku_info、base_province、base_region、order_info、order_detail。抽取的具体方法和逻辑大同小异。首先需要编写hiveSQL的查询语句,查询出数据库中最大的时间或者id。接着根据时间或者id在mysql中进行查找。然后将查找到的结果再追加写入到hive的表中,同时增加相关的列。

package com.hbzy.GZ03

import com.hbzy.GZ03.gz03utils.{appendHive, loadJDBC}
import org.apache.spark.SparkConf
import org.apache.spark.sql.functions.{current_timestamp, lit}
import org.apache.spark.sql.{DataFrame, SparkSession}

import java.sql.Timestamp

object gz03job {

  def main(args: Array[String]): Unit = {
    val SparkConf = new SparkConf().setMaster("local[*]").setAppName("gz03job")
    val session: SparkSession = SparkSession
      .builder() // 环境
      .config(SparkConf) // 各种配置项
      .config("hive.metastore.uris", "thrift://192.168.79.132:9083") // 加载元数据
      // 打开hive动态分区
      .config("hive.exec.dynamic.partition", "true")
      .config("hive.exec.dynamic.partition.mode", "nonstrict")
      // 需要根据分区值,覆盖原来的分区时,需要配置的参数
//      .config("spark.sql.source.partitionOverwriteMode", "dynamic")
      .enableHiveSupport() // 获得hive支持
      .getOrCreate() // 创建

    // 增量抽取user_info
    job_user_info(session)
    // 增量抽取sku_info
    job_sku_info(session)
    // 增量抽取base_province
    job_base_province(session)
    // 增量抽取base_region
    job_base_region(session)
    // 增量抽取order_info
    job_order_info(session)
    // 增量抽取order_detail
    job_order_detail(session)

  }

  // 增量抽取user_info    operate_time或create_time
  def job_user_info(sparkSession: SparkSession):Unit = {
    // 首先计算出user_info存量数据的最大时间
    val hive_max_time = "select greatest(max(operate_time), max(create_time)) max_time from ds_ods.user_info"
    val df: DataFrame = sparkSession.sql(hive_max_time)
//    df.show()
    val max_time = df.first().getTimestamp(0)
//    println(max_time)

    // ---------查询mysql
    // 定义mysql查询语句
    val querySQL = s"select * from user_info where operate_time > '${max_time}' or create_time > '${max_time}'"
    // 将查询mysql的options参数定义为jdbcMap
    val jdbcMap = Map(
      "driver" -> "com.mysql.jdbc.Driver",
      "url" -> "jdbc:mysql://192.168.79.132:3306/shtd_store?useSSL=false",
      "query" -> querySQL,
      "user" -> "root",     // 致命性小错误,这里的参数是user而不是username
      "password" -> "admin"
    )
    // 查询
    val frame: DataFrame = loadJDBC(sparkSession, jdbcMap)
    frame.show()

    // 增加静态分区
    val frame1: DataFrame = frame.withColumn(colName = "etl_date", lit("20230820"))
    // 定义hiveMap,写入hive访问的基本信息
    val hiveMap = Map(
      "db" -> "ds_ods",
      "tb" -> "user_info",
      "partitionColumn" -> "etl_date"
    )
    // 将分区后的数据增量写入hive中
    appendHive(sparkSession, frame1, hiveMap)

  }

  // 抽取sku_info   条件create_time
  def job_sku_info(sparkSession: SparkSession):Unit = {
    // 计算出sku_info中的最大时间
    // 编写hive查询语句
    val hive_max_time = "select max(create_time) max_time from ds_ods.sku_info"
    // 运行查询语句
    val df: DataFrame = sparkSession.sql(hive_max_time)
    df.show()
    val max_time: Timestamp = df.first().getTimestamp(0)
    println(max_time)

    // 定义mysql查询语句
    val querySQL = s"select * from sku_info where create_time > '${max_time}'"
    // 定义jdbcMap
    val jdbcMap = Map(
      "driver" -> "com.mysql.jdbc.Driver",
      "url" -> "jdbc:mysql://192.168.79.132:3306/shtd_store?useSSL",
      "query" -> querySQL,
      "user" -> "root",
      "password" -> "admin"
    )
    // 执行查询
    val frame: DataFrame = loadJDBC(sparkSession, jdbcMap)
    frame.show()

    // 增加静态分区
    val frame1: DataFrame = frame.withColumn("etl_date", lit("20230820"))
    // 定义hiveMap
    val hiveMap = Map(
      "db" -> "ds_ods",
      "tb" -> "sku_info",
      "partitionColumn" -> "etl_date"
    )
    // 写入
    appendHive(sparkSession, frame1, hiveMap)
  }

  // 抽取base_province  条件id
  def job_base_province(sparkSession: SparkSession):Unit={
    // 编写hive查询语句,计算最大的id
    val hive_max_id = "select max(id) max_id from ds_ods.base_province"
    // 执行查询
    val df: DataFrame = sparkSession.sql(hive_max_id)
    // 数据转换
    val max_id = df.first().getLong(0)

    // 通过id来查询mysql
    // 定义mysql查询语句
    val querySQL = s"select * from base_province where id > '${max_id}'"
    // 定义jdbcMap
    val jdbcMap = Map(
      "driver" -> "com.mysql.jdbc.Driver",
      "url" -> "jdbc:mysql://192.168.79.132:3306/shtd_store?useSSL=false",
      "query" -> querySQL,
      "user" -> "root",
      "password" -> "admin"
    )
    // 通过工具方法执行
    val frame: DataFrame = loadJDBC(sparkSession, jdbcMap)
    frame.show()

    // 增加create_time以及etl_date分区
    val frame1: DataFrame = frame
      .withColumn("create_time", current_timestamp())
      .withColumn("etl_date", lit("20230820"))

    // 定义hiveMap
    val hiveMap = Map(
      "db" -> "ds_ods",
      "tb" -> "base_province",
      "partitionColumn" -> "etl_date"
    )

    // 执行增量抽取
    appendHive(sparkSession, frame1, hiveMap)

  }

  // 增量抽取base_region  条件id
  def job_base_region(sparkSession: SparkSession):Unit={
    // 查询最大id
    val hive_max_id = "select max(id) from ds_ods.base_region"
    // 执行
    val df: DataFrame = sparkSession.sql(hive_max_id)
    // 转换  // base_region中的这张表的id类型为varchar导致抽取到的类型为string类型,string类型不能直接转换long类型
    val max_id: Long = df.first().getString(0).toLong
    println(max_id)

    // 根据id来查询
    val querySQL = s"select * from base_region where id > '${max_id}'"
    // 编写jdbcMap
    val jdbcMap = Map(
      "driver" -> "com.mysql.jdbc.Driver",
      "url" -> "jdbc:mysql://192.168.79.132/shtd_store?useSSL=false",
      "query" -> querySQL,
      "user" -> "root",
      "password" -> "admin"
    )

    // 执行查询
    val frame: DataFrame = loadJDBC(sparkSession, jdbcMap)
    frame.show()

    // 增加create_time和etl_date分区
    val frame1: DataFrame = frame
      .withColumn("create_time", current_timestamp())
      .withColumn("etl_date", lit("20230820"))

    // 编写hiveMap
    val hiveMap = Map(
      "db" -> "ds_ods",
      "tb" -> "base_region",
      "partitionColumn" -> "etl_date"
    )

    appendHive(sparkSession, frame1, hiveMap)
  }

  // 增量抽取order_info   条件operate_time和create_time
  def job_order_info(sparkSession: SparkSession):Unit={
    // 查询hive中的最大时间
    val hive_max_time = "select greatest(max(create_time), max(operate_time)) max_time from ds_ods.order_info"
    // 执行
    val df: DataFrame = sparkSession.sql(hive_max_time)
    // 转换
    val max_time: Timestamp = df.first().getTimestamp(0)
    println(max_time)

    // 根据使时间查询
    val querySQL = s"select * from order_info where operate_time > '${max_time}' or create_time > '${max_time}'"
    // 定义jdbcMap
    val jdbcMap = Map(
      "driver" -> "com.mysql.jdbc.Driver",
      "url" -> "jdbc:mysql://192.168.79.132/shtd_store?useSSL",
      "query" -> querySQL,
      "user" -> "root",
      "password" -> "admin"
    )

    val frame: DataFrame = loadJDBC(sparkSession, jdbcMap)
    frame.show()

    // 增加列
    val frame1: DataFrame = frame.withColumn("etl_date", lit("20230820"))

    // 编写hiveMap
    val hiveMap = Map(
      "db" -> "ds_ods",
      "tb" -> "order_info",
      "partitionColumn" -> "etl_date"
    )

    // 执行
    appendHive(sparkSession, frame1, hiveMap)

  }

  // 增量抽取order_detail   条件create_time   2020-04-25 18:47:14.0
  def job_order_detail(sparkSession: SparkSession):Unit={
    // 查询hive中的最大时间
    val hive_max_time = "select max(create_time) from ds_ods.order_detail"
    // 执行查询
    val df: DataFrame = sparkSession.sql(hive_max_time)
    // 转换
    val max_time = df.first().getTimestamp(0)
    println(max_time)

    // 根据时间查询mysql
    val querySQL = s"select * from order_detail where create_time > '${max_time}'"
    // 编写jdbcMap
    val jdbcMap = Map(
      "driver" -> "com.mysql.jdbc.Driver",
      "url" -> "jdbc:mysql://192.168.79.132:3306/shtd_store?useSSL",
      "query" -> querySQL,
      "user" -> "root",
      "password" -> "admin"
    )

    // 查询
    val frame: DataFrame = loadJDBC(sparkSession, jdbcMap)
    frame.show()

    // 增加分区
    val frame1: DataFrame = frame.withColumn("etl_date", lit("20230820"))
    // 编写hiveMap
    val hiveMap = Map(
      "db" -> "ds_ods",
      "tb" -> "order_detail",
      "partitionColumn" -> "etl_date"
    )
    appendHive(sparkSession, frame1, hiveMap)
  }

}

  • 7
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 大数据离线数据抽取的步骤一般包括以下几个阶段: 1. 数据采集:采集需要处理的数据,包括结构化数据和非结构化数据。 2. 数据清洗:清洗采集到的数据,去除重复数据、无效数据和错误数据。 3. 数据预处理:对清洗后的数据进行处理,包括数据去噪、数据过滤、数据转换等,以便后续的分析和挖掘。 4. 数据集成:将不同来源的数据进行集成,生成一个完整的数据集。 5. 数据转换:将数据转换为目标系统可识别的格式,如将非结构化数据转换为结构化数据。 6. 数据归约:对数据进行归约操作,包括聚合、抽样等,以减小数据规模。 7. 数据存储:将处理后的数据存储到相应的数据仓库中,以便后续的分析和挖掘。 以上就是大数据离线数据抽取的基本步骤。 ### 回答2: 大数据离线数据抽取是指从大规模数据中提取有价值的数据并进行处理分析的过程。以下是大数据离线数据抽取的详细步骤: 1. 数据源选择:确定抽取数据的来源,可以是各种数据库、文件或日志等。 2. 数据预处理:对原始数据进行数据清洗和预处理,包括去除重复值、处理缺失值、格式转换等,以保证数据的质量和一致性。 3. 数据抽取:通过数据抽取工具或技术,将预处理后的数据数据源中提取出来,常用的抽取方式有全量抽取和增量抽取。 4. 数据转换:将抽取出的数据进行转换、整合和归并,使其符合目标数据模型和格式要求,常用的技术有ETL(Extract-Transform-Load)工具和技术。 5. 数据加载:将转换后的数据加载到目标数据库或目标存储系统中,以便进行后续的数据分析和应用。 6. 数据分析:对加载后的数据进行分析和挖掘,可以使用各种数据分析和挖掘工具,如数据挖掘算法、统计分析等,以获取有价值的信息和洞察。 7. 数据可视化:将分析结果通过可视化工具展示出来,如图表、报表、仪表盘等,以便用户更直观地理解和利用数据。 8. 数据挖掘和建模:根据分析结果,进行数据挖掘和建模,以发现数据中的潜在模式、规律和关联,并构建相应的预测和决策模型。 9. 模型评估和优化:对建立的模型进行评估和优化,通过模型评估指标和反馈来不断优化模型的准确性和性能。 10. 应用和反馈:将分析结果和建立的模型应用到实际场景中,并根据实际应用情况进行反馈和调整,以持续提高数据分析的效果和价值。 以上是大数据离线数据抽取的主要步骤,每个步骤都非常重要,对于有效地利用大数据进行数据分析和挖掘具有关键作用。 ### 回答3: 大数据离线数据抽取是指从海量数据中提取所需数据的过程。以下是详细的步骤: 1. 数据源识别:首先确定需要抽取数据的源头,可以是关系数据库、文本文件、日志文件等各种数据源。 2. 数据源连接:与数据源建立连接,确保能够获取数据。连接方式可以是使用数据库连接工具、FTP、API等。 3. 数据提取规则设计:根据需求确定数据提取的规则,包括哪些表需要抽取抽取的字段是什么等。这一步需要保证提取的数据能够满足后续使用的需求。 4. 数据抽取:根据提取规则,使用特定的工具或编写代码进行数据抽取操作。常用的工具包括Sqoop、Flume、Kettle等。 5. 数据转换:将抽取的原始数据转换成符合目标要求的格式。这一步可能包括数据清洗、格式转换、字段拆分合并等处理操作,以确保数据的准确性和一致性。 6. 数据加载:将转换后的数据加载至目标位置,可以是数据仓库、分析平台、报表工具等。加载方式可以是覆盖式更新或增量更新等。 7. 数据校验和验证:对加载后的数据进行校验和验证,确保数据的完整性和正确性。可以通过对比原始数据和转换后数据的差异、查询数据的准确性等方式进行验证。 8. 数据存储和备份:将已抽取数据进行存储和备份,以便后续使用和恢复。可以选择合适的存储介质和备份策略。 9. 数据可视化和分析:将存储的数据通过数据可视化工具进行展示和分析,帮助用户理解和利用数据,从中发现潜在的业务价值。 10. 定期维护和优化:根据实际需求和数据变化情况,定期对数据抽取过程进行维护和优化,保证数据抽取的效率和准确性。 总之,大数据离线数据抽取的步骤包括数据源识别、数据源连接、数据提取规则设计、数据抽取数据转换、数据加载、数据校验和验证、数据存储和备份、数据可视化和分析以及定期维护和优化。通过这些步骤,我们可以从海量数据中提取并利用有用的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值