相信很多在用CDP7的小伙伴都遇到了Spark里面不再支持spark-sql的问题

这里给出两种解决方案:spark-submit与spark-shell

cloudera官方给的解决方案

https://docs.cloudera.com/cdp-private-cloud-base/7.1.5/developing-spark-applications/topics/spark-sql-example.html

基于这个方案,这里提供两种通用方案

test.hql

CREATE DATABASE SPARK;
CREATE TABLE SPARK.TEST(ID INT, NAME STRING);
INSERT INTO SPARK.TEST VALUES(1,'Daniel');
SELECT
 * 
 FROM SPARK.TEST;
  • spark-submit(推荐)

    编写Scala代码来解决这个问题,这里以读取HDFS上的SQL为例

    package sparksql
    
    import org.apache.spark.sql.{Encoders, SparkSession}
    
    import scala.collection.JavaConversions._
    
    /**
      * @Author Daniel
      * @Description Spark运行HDFS上的SQL
      **/
    object RunSparkSQL {
      def main(args: Array[String]): Unit = {
        if (args == null || args.length < 1) {
          println(
            """
              |parameter errors! Usage: <SQL>
              |SQL: a spark sql command
            """.stripMargin
          )
          System.exit(-1)
        }
    
        val spark = SparkSession.builder()
          // hive的配置
          .config("hive.metastore.uris", "thrift://hadoop03:9083")
          .appName(RunSparkSQL.getClass.getSimpleName)
          .enableHiveSupport()
          .getOrCreate()
    
        /*
        以spark.read的方式去读文本文件,会将文件读成一个表
        表的话,就涉及到很多列,但这里为SQL,是没有多列的,
        所以以一个不存在的分割符来切割,表示这里只需要一列
        !!!如果是低版本的Spark只支持一个分隔符,改为option("sep", "@")
         */
        val df = spark.read.option("sep", "@@@").csv(args(0))
        // 将df里面数据的格式强制转换为String类型,将其转成一个集合
        val rowList = df.as(Encoders.STRING).collectAsList
        var rows = ""
        // 添加空格,避免SQL连在一起产生语法错误
        for (row <- rowList) {
          rows += " " + row
        }
        // 如果有多个SQL,以分号来分割
        val sqlArr = rows.split(";")
        // 运行每一个SQL,注意这里要导入scala.collection.JavaConversions._才能进行遍历
        for (s <- sqlArr) {
          // 显示完整结果
          spark.sql(s).show(false)
        }
        spark.stop()
      }
    }
    

    将代码打成jar包,上传到hdfs

    hdfs dfs -put test.hql /hive_data
    hdfs dfs -put runsparksql.jar /hive_data/jars
    

    然后编写Shell脚本

    runspark.sh

    spark-submit \
    --class sparksql.RunSparkSQL \
    --master local[*] \
    --deploy-mode client \
    --total-executor-cores 2 \
    --executor-cores 1 \
    --executor-memory 600M \
    hdfs:///hive_data/jars/runsparksql.jar \
    $1
    

    运行脚本

    bash runspark.sh hdfs:///hive_data/test.hql
    

    结果

    ++
    ||
    ++
    ++
    
    ++
    ||
    ++
    ++
    
    ++
    ||
    ++
    ++
    
    +---+------+
    |ID |NAME  |
    +---+------+
    |1  |Daniel|
    +---+------+
    

    hive里面也可以查看

CDP7无SparkSQL解决方案_spark

  • spark-shell

    编写shell脚本来解决这个问题,在spark的bin目录下新建脚本

    vi $SPARK_HOME/bin/spark2-sql
    

    spark2-sql

    #!/bin/bash
    
    if [[ $1 = "-e" ]];then
       sql=$2
    elif [[ $1 = "-f" ]];then
       sql=`cat $2`
    else
      echo "Usage:"
      echo "--------------------------------------------------------"
      echo "spark2-sql.sh -f [SQL filename] : execute a sql file"
      echo "spark2-sql.sh -e [SQL] : execute a sql"
      echo "--------------------------------------------------------"
    fi
    
    if [[ ${sql} =~ ';' ]];then
      i=1
      while((1==1))
      do
         splitchar=`echo $sql|cut -d ";" -f$i`
         if [ "$splitchar" != "" ];then
            ((i++))
            sparksql=${sparksql}"spark.sql(\"$splitchar\").show();"
         else
            break
         fi
      done
    else
      sparksql = "spark.sql(\"$sql\").show();"
    fi
    echo $sparksql
    echo ${sparksql} | spark-shell
    
    

    直接运行即可,-e加具体sql,-f加文件(目前只支持Local的文件)

    spark2-sql -e 'select current_timestamp;'
    spark2-sql test.hql
    

CDP7无SparkSQL解决方案_Spark_02