Pyspark 读取本地csv文件,插入parquet格式的hive表中

在CDSW上模型运行出结果,为csv文件。由于报表的需求,要将csv文件插入到parquet格式中的表中。

在其中遇到了很多坑,在此记下来,希望能帮助到遇到同样问题的人。


1、初始化配置创建Spark Session。

(注意事项:Spark2.0版本开始将sqlContext、hiveContext统一整合为SparkSession)

2、读取文件并转换为Spark DataFrame格式。

(坑1:路径和语法问题。spark.read.csv函数可以直接将csv读取为Spark DataFrame格式,但CDSW上的PySpark连接的是Hive表,而并非本地环境。因此本地环境的csv需要先用pd.read_csv读取为pandas DataFrame格式后,再转为spark.createDataFrame格式)

3、将转换后的DF注册为一张临时表。具体语法如下:

data.createTempView("tableTemp")

(坑2:临时表无法查看。创建的是临时表,因此用df.show()等函数无法查看其中的内容等等参数。)

4、通过Spark SQL创建Hive外部表。具体语法如下:

spark.sql("""create external table if not exists tableExternal
         (mac string, phone_brand string, enter_time timestamp, first_time timestamp,
          last_time timestamp,region string, screen string, stay_time int)
          stored as parquet location 'hdfs://master:9000//test'""")

(坑3:权限问题。虽然数次和数据中心沟通权限问题,显示yfzx2的权限是all。但是死活就是提示 have no privileges,创建不了表。而数据中心的人员在后台,用同一租户同一语句却创建成功。没其他办法,创建外部表的这一步,最后是用hue平台解决的。)

(坑4:SQL换行问题。之前只会用\斜杠来换行,太麻烦。向同事学习了新的写法,能直接换行。用三个引号将SQL语句括起来,这样整个语句就是字符串格式了,随便回车换行都没问题。)

(注意事项:(1)对于row format delimited fields terminated by '\t',这个语法只适用于存储文件格式为textFile,不适用于parquet。(2)对于location,一定要写hdfs的全路径。)

5、通过Spark SQL执行insert语句,将数据插入到Hive表中。具体语法如下:

spark.sql("insert overwrite table tableExternal select * from tableTemp")

这样就完成将本地csv数据以parquet形式加载到Hive表中。可以到Hive表中验证数据是否成功载入。


至此本应大功告成,但居然还出bug。

在Hive上验数时,发现表里中文全部乱码。

原因是CDSW上的PySpark中,集成Python的版本是2.7。Python2.7的默认编码是ASCII,并非Python3的UTF-8。

尝试解决1:用Python3写SQL插入表。由于版本不兼容,失败。

尝试解决2:在创建临时表时不能有控制,因此用了df.fillna(''-1'')。换成Python3把空值先替换,然后在Python2环境下直接插入。依然乱码,失败。

尝试解决3:用setdefaultcoding语句,修改外部表的编码为UTF-8。失败,依然乱码。编码换成ASCII、GBK、GB2312,依然失败。

尝试解决4:修改Python2的编码环境。语句前加上_*_ coding:UTF-8 _*_,依然失败,乱码。sys.getdefaultencoding() 发现Python2的编码是ASCII,reload(sys)重新加载,然后用sys.setdefaultencoding('utf-8')修改系统编码为UTF-8。print(sys.getdefaultencoding() )显示编码已被修改为UTF-8。但是跑一遍流程,依然乱码,失败。

尝试解决5:将csv文件转为parquet格式,然后再直接通过parquet格式插入表里。乱码,失败。

尝试解决6,最终成功省略创建临时表的那一步,直接将csv文件插入到textFile格式的外部表,再从textFile的外部表load入parquet格式的外部表。


其他一些注意事项:

1. csv文件的分隔符默认为逗号',',其中某一列数据包含文本和同样的逗号,例如这一列是'[你好,吃了没,再见]'。在excel和dataframe中显示正常,但是插入表后这列中的逗号也成了分隔符,列都错位了,例如插入表被分成了三列'[你好','吃了没','再见]'。因此在pd.to_csv时设置sep为';',然后读取时pd.read_csv设置sep为';',在创建csv外部表时也设置terminated by ';'。

2. 在尝试解决时,需要压缩文件。而CDSW的系统超级烂,直接上传较大的csv或parquet文件会丢失,因此需要先压缩。注意压缩时不能用7z压缩,因为没办法解压。需要压缩成zip格式后,在终端用unzip命令解压缩。

发布了330 篇原创文章 · 获赞 71 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/sinat_26811377/article/details/103188990