• spark sql 导出数据


    如果用户希望在spark sql 中,执行某个sql 后,将其结果集保存到本地,并且指定csv 或者 json 格式,在 beeline 中,实现起来很麻烦。通常的做法是将其create table tempTable as *** ,通过将结果集写入到新的临时表中,进行保存,然后再通过其他方式export 到本地。

    这种方式,对于 HDFS 是可行到,但是如果数据是保存在像SequoiaDB 中,就比较难办了。因为spark 向 SequoiaDB 写入记录时,可能部分task 会失败重试,这样就容易造成SequoiaDB 目标表中写入了重复记录,从而造成数据不准确的问题。

    因此,需要寻找一种的新的方式,将其结果集准确地读取出来,并且写入本地文件。

    在网上有很多替代方案,无外乎是通过beeline 或者 spark-sql ,执行 SQL 命令,通过重定向的方式,将结果集保存到指定文件中。

    这样的方式,首先不讨论其输出格式的问题,最无法让人接受的是,spark-sql 需要将所有的结果数据收集到一个 Driver 进程中后,才会开始输出终端。这个过程有以下 3 个问题

    1. 时间久,如果数据量大了,Driver 收集的过程会很久,并且通过top 可以查看到进程CPU 飙升
    2. 容易OOM,当数据量增大后,因为需要将所有结果数据存储在内存中,一旦数据量用超了,就抛出 OOM 的错误,一切前功尽弃
    3. 输出格式,因为保存本地文件的内容就是输出终端的数据,CSV 格式不友好,有时候甚至会因为不可见字符而导致整个本地文件格式错乱,最终导致数据无法恢复

    所以本文主要是向读者们介绍一种新的方式,直接使用 scala / python 语言开发的程序,利用 RDD 将其结果数据保存本地,输出格式支持 CSV 和 JSON。

    • scala 版本

    scala 版本作者没有直接编写程序,但是通过 spark-shell 进行了验证

    import org.apache.spark.sql.hive.HiveContext
    // sc - existing spark context
    val sqlContext = new HiveContext(sc)
    val df = sqlContext.sql("SELECT * FROM test_sdb")
    df.coalesce(1).write.format("com.databricks.spark.csv").mode("overwrite").option("header", "true").save("/opt/sequoiadb/chenfool")

    如果有用户喜欢这个方式,可以考虑将程序打包成jar 包来执行。

    导出格式的更多参数,请参考 python 版本

    • python 版本

    在执行python 的脚本前,首先需要设置一下环境变量

    export SPARK_HOME=/root/software/spark-2.1.1-bin-hadoop2.7
    export PYTHONPATH=${SPARK_HOME}/python/:${SPARK_HOME}/python/lib/py4j-0.10.4-src.zip;

    注意:py4j-0.10.4-src.zip 文件名可能随不同的spark 版本有所变化

    然后准备以下脚本程序, spark_sql_export.py

    import atexit
    import os
    import platform
    
    
    import pyspark
    from pyspark.context import SparkContext
    from pyspark.sql import SparkSession, SQLContext
    
    spark = SparkSession 
        .builder 
        .enableHiveSupport() 
        .getOrCreate()
    
    df = spark.sql("SELECT * FROM test_sdb limit 100")
    
    #df.coalesce(1).write.format("org.apache.spark.sql.json").mode("overwrite") 
    #  .save("/opt/sequoiadb/chenfool")
    
    
    df.coalesce(1).write.format("com.databricks.spark.csv").mode("overwrite") 
      .option("enforceSchema", "false") 
      .option("quoteAll", "true") 
      .option("escapeQuotes", "false") 
      .option("header", "true") 
      .option("delimiter", "|") 
      .option("charToEscapeQuoteEscaping", """) 
      .option("inferSchema", "true") 
      .option("ignoreLeadingWhiteSpace", "false") 
      .option("ignoreTrailingWhiteSpace", "false") 
      .save("/opt/sequoiadb/chenfool")

    执行方式

    python spark_sql_export.py

    结果数据就会被保存在 /opt/sequoiadb/chenfool/part-00000* 文件中。

    结果数据只会被保存在一个文件中,因为设置了 coalesce 参数。

    JSON 格式请参考 spark_sql_export.py 注释部分。

    CSV 的详细参数,可以参考spark 源码:${SPARK_HOME}/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/csv/CSVOptions.scala 

    注意:

    在spark 2.1.1 版本中,ignoreLeadingWhiteSpace 和 ignoreTrailingWhiteSpace 参数无法生效,默认值为:true。在 spark 2.4.0 版本中,经过测试,这两个参数才能够生效。如果要求保存的数据中不做 trim 操作,只能够将spark 升级为2.4.0 版本。

    本博客参考了之前 spark 学习(二) 的内容,里面有介绍如果利用python 来执行spark 的程序的说明,感兴趣的读者们可以移步查阅

  • 相关阅读:
    关于applet
    Hello.java
    filter用户授权的例子
    logfilter
    Java EE课程设计——企业人力资源管理系统
    条件查询、SQL、JPQL、HQL比较
    web service和ejb的区别
    RPC
    hashcode()和equals()的区别
    关于JSON
  • 原文地址:https://www.cnblogs.com/chenfool/p/10808455.html
Copyright © 2020-2023  润新知