文章目录
源数据描述
在 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
中的逗号被识别成了字段间隔符,在那之后的字段整体发生了错位,产生了数据异常。
问题解决
- 替换成其它分隔符
- 不指定分隔符,用 Hive 的默认分隔符
\u0001
。
在问题复现这里我们可以很容易的发现问题产生的原因,在实际开发中,字段特别多,而且不一定每个字段都会使用到,我这里是因为使用了发生错误的字段,所以才发现了这个问题,提醒各位在建表时需要格外注意指定的字段分隔符。
虽然是个很小的 BUG,但是往往容易错的就是这种小 BUG!
可恶,又是两个小时!
版权归原作者 月亮给我抄代码 所有, 如有侵权,请联系我们删除。