0


使用 Spark 抽取 MySQL 数据到 Hive 时某列字段值出现异常(字段错位)

文章目录

源数据描述

在 MySQL 中建立了表

order_info

,其字段信息如下所示:

+--------------------+------------------+------+-----+-------------------+-----------------------------+| Field              |Type|Null|Key|Default| Extra                       |+--------------------+------------------+------+-----+-------------------+-----------------------------+| order_id           |int(10)unsigned|NO| PRI |NULL|auto_increment|| order_sn           |varchar(100)|NO||NULL||| address            |varchar(100)|NO||NULL||| create_time        |varchar(100)|NO||NULL||| pay_time           |varchar(100)|NO||NULL||+--------------------+------------------+------+-----+-------------------+-----------------------------+

除了

order_id

字段,其余字段类型都为

varchar(100)

根据

create_time

降序查询前

20

列,输出结果如下:

+----------+------------------+----------------------------------------------------------------------------------------+----------------+----------------+| order_id | order_sn         | address                                                                                | create_time    | pay_time       |+----------+------------------+----------------------------------------------------------------------------------------+----------------+----------------+|36876|2022091196411460| 江苏省南京市中央路2014271号第一层110店铺11层                                           |20220911220617|NULL||36877|2022091196411460| 江苏省南京市中央路2014271号第一层110店铺11层                                           |20220911220617|20220911232917||36878|2022091196411460| 江苏省南京市中央路2014271号第一层110店铺11层                                           |20220911220617|20220911232917||36879|2022091196411460| 江苏省南京市中央路2014271号第一层110店铺11层                                           |20220911220617|20220911232917||36880|2022091196411460| 江苏省南京市中央路2014271号第一层110店铺11层                                           |20220911220617|20220911232917||36798|2022091196213791| 江苏省昆山市柏庐南路9991713号商业街商铺11713号13层                                     |20220911220552|NULL||36799|2022091196213791| 江苏省昆山市柏庐南路9991713号商业街商铺11713号13层                                     |20220911220552|20220912115152||36800|2022091196213791| 江苏省昆山市柏庐南路9991713号商业街商铺11713号13层                                     |20220911220552|20220912115152||36801|2022091196213791| 江苏省昆山市柏庐南路9991713号商业街商铺11713号13层                                     |20220911220552|20220912115152||36811|2022091010006041| 江苏省南京市中山路3213071号鼓楼医院南扩新院区门诊大楼一楼5层                           |20220911220057|NULL||36812|2022091010006041| 江苏省南京市中山路3213071号鼓楼医院南扩新院区门诊大楼一楼5层                           |20220911220057|20220912103157||36813|2022091010006041| 江苏省南京市中山路3213071号鼓楼医院南扩新院区门诊大楼一楼5层                           |20220911220057|20220912103157||36814|2022091010006041| 江苏省南京市中山路3213071号鼓楼医院南扩新院区门诊大楼一楼5层                           |20220911220057|20220912103157||37448|2022091154427501| 上海市上海市杨树浦路26887789号上海国际时尚中心18层                                     |20220911213924|NULL||37449|2022091154427501| 上海市上海市杨树浦路26887789号上海国际时尚中心18层                                     |20220911213924|20220912115924||37450|2022091154427501| 上海市上海市杨树浦路26887789号上海国际时尚中心18层                                     |20220911213924|20220912115924||37451|2022091154427501| 上海市上海市杨树浦路26887789号上海国际时尚中心18层                                     |20220911213924|20220912115924||37227|2022091178845429| 浙江省宁波市鄞州区四明中路9996584号万达广场银泰百货1F15层                              |20220911212820|NULL||37228|2022091178845429| 浙江省宁波市鄞州区四明中路9996584号万达广场银泰百货1F15层                              |20220911212820|20220912110220||37229|2022091178845429| 浙江省宁波市鄞州区四明中路9996584号万达广场银泰百货1F15层                              |20220911212820|20220912110220|+----------+------------------+----------------------------------------------------------------------------------------+----------------+----------------+

可以在这里看到原始数据的形态。

问题复现

现在我对这个问题进行复现,在下面这段代码里,我在 Hive 中的

ods

层建立了 MySQL 的对应表

order_info

,其字段信息如下所示:

order_id                int                                         
order_sn                string
address                 string
create_time             string
pay_time                string                                      
etl_date                string

同样除了

order_id

字段,其余字段类型都为

string

,其中

etl_date

字段为该表的分区字段。

importorg.apache.spark.sql.SparkSession

object Test{def main(args: Array[String]):Unit={val spark: SparkSession = SparkSession
                .builder().appName("Test").master("local[*]").enableHiveSupport().getOrCreate()// TODO 读取 MySQL 表数据
        spark.read.format("jdbc").option("driver","com.mysql.jdbc.Driver").option("url","jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8").option("user","root").option("password","123456").option("dbtable","order_info").load().createOrReplaceTempView("order_info")// TODO 在 Hive 中 ods 层创建表
        spark.sql("create database if not exists ods")

        spark.sql("drop table if exists ods.order_info")

        spark.sql("""
              |create table ods.order_info(
              |     order_id            int,
              |     order_sn            string,
              |     address             string,
              |     create_time         string,
              |     pay_time            string)
              |partitioned by(etl_date string)
              |row format delimited fields terminated by ','
              |""".stripMargin)// TODO 往表中写入数据
        spark.sql("""
              |insert into ods.order_info partition(etl_date="20230425")
              |select
              |     order_id,
              |     order_sn,
              |        address,
              |     create_time,
              |     pay_time
              |from
              |     order_info
              |""".stripMargin)// TODO 读取写入的数据
        spark.sql("""
              |select
              |     order_id,
              |     order_sn,
              |     address,
              |     create_time,
              |     pay_time
              |from
              |     ods.order_info
              |where
              |     order_sn = "2022031949619563"
              |""".stripMargin).show(20,truncate =false)

        spark.stop()}}

抽取完成后,在 Hive 中查询

order_info

表订单编号值为

2022031949619563

的数据,输出结果如下:

+--------+----------------+-----------------------------------------------------------+-----------+--------------+|order_id|order_sn        |address                                                    |create_time|pay_time      |+--------+----------------+-----------------------------------------------------------+-----------+--------------+|688|2022031949619563|浙江省杭州市教工路264370号世贸丽晶城欧美中心24370号楼G区107|108室13层   |20220320184807||689|2022031949619563|浙江省杭州市教工路264370号世贸丽晶城欧美中心24370号楼G区107|108室13层   |20220320184807||690|2022031949619563|浙江省杭州市教工路264370号世贸丽晶城欧美中心24370号楼G区107|108室13层   |20220320184807||691|2022031949619563|浙江省杭州市教工路264370号世贸丽晶城欧美中心24370号楼G区107|108室13层   |20220320184807|+--------+----------------+-----------------------------------------------------------+-----------+--------------+

我们会发现,其中

create_time

的值变成了一个中文字符串。

我们去 MySQL 源数据中核查一下该订单编号的数据,查询结果如下:

+----------+------------------+-----------------------------------------------------------------------------------------------+----------------+----------------+| order_id | order_sn         | address                                                                                       | create_time    | pay_time       |+----------+------------------+-----------------------------------------------------------------------------------------------+----------------+----------------+|688|2022031949619563| 浙江省杭州市教工路264370号世贸丽晶城欧美中心24370号楼G区107,108室13层                                   |20220320184807|NULL||689|2022031949619563| 浙江省杭州市教工路264370号世贸丽晶城欧美中心24370号楼G区107,108室13层                                   |20220320184807|20220321044607||690|2022031949619563| 浙江省杭州市教工路264370号世贸丽晶城欧美中心24370号楼G区107,108室13层                                   |20220320184807|20220321044607||691|2022031949619563| 浙江省杭州市教工路264370号世贸丽晶城欧美中心24370号楼G区107,108室13层                                   |20220320184807|20220321044607|+----------+------------------+-----------------------------------------------------------------------------------------------+----------------+----------------+

可以通过上下文对比轻松发现问题,数据抽取完成后,字段值出现了异常,那么为什么会这样呢?

问题解析

这是由于我们在创建 Hive 对应表时指定的字段分隔符是逗号

","

,所以在写入数据时,会默认将逗号作为字段分隔符。

        spark.sql("""
              |create table ods.order_info(
              |     order_id            int,
              |     order_sn            string,
              |     address             string,
              |     create_time         string,
              |     pay_time            string)
              |partitioned by(etl_date string)
              |row format delimited fields terminated by ','
              |""".stripMargin)

这里导致了字段

address

中的逗号被识别成了字段间隔符,在那之后的字段整体发生了错位,产生了数据异常。

问题解决

  1. 替换成其它分隔符
  2. 不指定分隔符,用 Hive 的默认分隔符 \u0001

在问题复现这里我们可以很容易的发现问题产生的原因,在实际开发中,字段特别多,而且不一定每个字段都会使用到,我这里是因为使用了发生错误的字段,所以才发现了这个问题,提醒各位在建表时需要格外注意指定的字段分隔符。

虽然是个很小的 BUG,但是往往容易错的就是这种小 BUG!

可恶,又是两个小时!

标签: hive mysql spark

本文转载自: https://blog.csdn.net/weixin_46389691/article/details/130367058
版权归原作者 月亮给我抄代码 所有, 如有侵权,请联系我们删除。

“使用 Spark 抽取 MySQL 数据到 Hive 时某列字段值出现异常(字段错位)”的评论:

还没有评论