Spark SQL :操作各种数据源笔记

参考

spark官网
DT大数据梦工厂

spark sql操作各种数据源的数据流转 :

各种数据源的输入 => RDD(lines) =>RDD(Rows) => DataFrame(注册临时表) => 分析与过滤(各种sql操作、机器学习等)=> RDD(Row) => 各种格式的输出

场景

Spark sql怎么操作各种数据源: json格式的文件、hive、mysql、hbase

分析

  • 以spark sql内置函数的agg的操作为例,解读 sql 数据流转

代码

package main.scala
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.hive.HiveContext
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.StructType
import org.apache.spark.sql.types.StructField
import org.apache.spark.sql.types.StringType
import org.apache.spark.sql.types.IntegerType
import org.apache.spark.sql.functions._

/**
 * 使用spark sql 内置函数对数据进行分析
 * 内置函数返回一个列Column
 * 分类:
 * 1、聚合函数 2、集合函数 3、日期、时间函数 4、数学函数 5、开窗函数 6、字符串处理函数 7、其他
 */
object sqlagg {

  def main(args: Array[String]): Unit = {

    val conf = new SparkConf().setMaster("local[*]").setAppName("sparkinnerfunctions")
    val sc = new SparkContext(conf)
    sc.setLogLevel("ERROR")
    val sqlContext = new SQLContext(sc)

    /*
     *  1. 获取数据源 - RDD(line)
     */
    val userData = Array(
      "2016-5-29,001,http://spark.apache.org/,1000",    
      "2016-5-20,001,http://spark.apache.org/,1090",  
      "2016-5-20,001,http://spark.apache.org/,1060",  
      "2016-5-30,002,http://spark.apache.org/,1000",  
      "2016-5-30,003,http://spark.apache.org/,1000",
      "2016-5-10,003,http://spark.apache.org/,1020",
      "2016-5-10,003,http://spark.apache.org/,1020",
      "2016-5-10,003,http://spark.apache.org/,1000"
    )
    var dataRDD = sc.parallelize(userData)

    /*
     * 2. 转换成 RDD(Row)
     */
    val rowRDD = dataRDD.map(line => {
      val splited = line.split(",")
      Row(splited(0),splited(1),splited(2),splited(3))
    })

    /*
     * 3. 指定Row的数据结构 并生成 DataFrame
     */
    val structTypes = StructType( Array(
            StructField("time",StringType,true),
            StructField("userid",StringType,true),
            StructField("url",StringType,true),
            StructField("amount",StringType,true)
                ) )
    val userDataDF = sqlContext.createDataFrame(rowRDD, structTypes)

    /*
     * 4 . 使用Spark SQL提供的内置函数对DataFrame进行操作(需要导入相关隐式转换信息)
     *   :内置函数生成column对象
     */
    import sqlContext.implicits._ 

    //按日期分类,然后进行聚合操作: 去重 userid, 计算每天的销售总量
    userDataDF.groupBy("time").agg('time, countDistinct('userid)).map(row=>Row(row(1),row(2))).collect().foreach(println)
    userDataDF.groupBy("time").agg('time, sum('amount)).show()
  }
}

执行结果

[2016-5-10,1]
[2016-5-20,1]
[2016-5-29,1]
[2016-5-30,2]

+---------+---------+-----------+
|     time|     time|sum(amount)|
+---------+---------+-----------+
|2016-5-10|2016-5-10|     3040.0|
|2016-5-20|2016-5-20|     2150.0|
|2016-5-29|2016-5-29|     1000.0|
|2016-5-30|2016-5-30|     2000.0|
+---------+---------+-----------+
  • 一. json

代码

package main.scala
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
/**
 - spark sql操作 本地json文件
 */
object DataFrameOps {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setMaster("local[*]").setAppName("DataFram Ops")
    val sqlContext = new SQLContext(new SparkContext(conf))

    val df = sqlContext.read.json("file:///home/hadoop/spark-1.6.0-bin-hadoop2.6/examples/src/main/resources/people.json")

    df.show
    df.printSchema
    df.select("name").show
    df.select("name", "age").show
    df.select(df("name"),df("age")+10).show
    df.filter(df("age")>10).show
  }
}

执行结果

+---+----+
|age|name|
+---+----+
| 30|Andy|
+---+----+

root
 |-- age: long (nullable = true)
 |-- name: string (nullable = true)

+----+
|name|
+----+
|Andy|
+----+

+----+---+
|name|age|
+----+---+
|Andy| 30|
+----+---+

+----+----------+
|name|(age + 10)|
+----+----------+
|Andy|        40|
+----+----------+

+---+----+
|age|name|
+---+----+
| 30|Andy|
+---+----+
  • 二. Hive

    1. 代码
package cool.pengych.spark.sql;
import org.apache.spark.SparkConf;
import org.apache.spark.SparkContext;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.hive.HiveContext;
/**
 * SparkSQL OPS  on Hive
 * @author pengyucheng
 *
 */
public class SparkSQL2Hive
{
    public static void main(String[] args) 
    {
        SparkConf config = new SparkConf().setAppName("SparkSQL2Hive");
        SparkContext sc = new SparkContext(config);


        HiveContext hiveContext = new HiveContext(sc);
        hiveContext.sql("use hive");
        hiveContext.sql("DROP TABLE IF EXISTS people");
        hiveContext.sql("CREATE TABLE IF NOT EXISTS people(name STRING,age INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'");

        /*
         * (把本地数据加载到Hive数据仓库中(背后实际上发生了数据的拷贝),
         * 当然也可以通过LOAD DATA INPATH去获取HDFS等上的数据到Hive(此时发生了数据的移动)
         */
        hiveContext.sql("LOAD DATA LOCAL INPATH '/home/pengyucheng/resource/people.txt' INTO TABLE people ");

        hiveContext.sql("DROP TABLE IF EXISTS peoplescores");
        hiveContext.sql("CREATE TABLE IF NOT EXISTS peoplescores(name STRING,score INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'");
        hiveContext.sql("LOAD DATA LOCAL INPATH '/home/pengyucheng/resource/peoplescores.txt' INTO TABLE peoplescores");

        /*
         * 通过HiveContext使用join直接基于Hive中的两张表进行操作
         */
        DataFrame resultDF = hiveContext.sql("SELECT pi.name,pi.age,ps.score  FROM people pi JOIN peoplescores ps ON pi.name = ps.name WHERE ps.score > 75");

        /*
         * 通过saveAsTable创建一张 Hive Managerd Table,数据的元数据和数据的具体位置都是由Hive数据仓库
         * 进行管理的,当删除该表的时候,数据也会一起被删除(磁盘上的数据不再存在)
         */
        hiveContext.sql("DROP TABLE IF EXISTS peopleinformationresult");
        resultDF.saveAsTable("peopleinformationresult");

        /*
         * 使用HiveContext的table方法可以直接读取Hive数据仓库中的Table并生成DataFrame,接下来就可以进行机器学习、图计算
         * 等各种复杂ETL操作
         */
        DataFrame dataFromHive = hiveContext.table("peopleinformationresult");
        dataFromHive.show();
    }
}
  • 三.SparkSQL JDBC 2 Mysql

package cool.pengych.spark.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.spark.SparkConf;
import org.apache.spark.SparkContext;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.VoidFunction;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.DataFrameReader;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.RowFactory;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;

import scala.Tuple2;
/**
 * SparkSQL 通过 JDBC 操作 MySQL数据库
 * @author pengyucheng
 *
 */
public class SparkSQLJDBC2MySQL
{
    public static void main(String[] args)
    {
        SparkConf config = new SparkConf().setMaster("local[*]").setAppName("SparkSQLJDBC2MySQL");
        SparkContext sc = new SparkContext(config);
        sc.addJar("/home/hadoop/spark-1.6.0-bin-hadoop2.6/lib/mysql-connector-java-5.1.39-bin.jar");
        SQLContext sqlContext = new SQLContext(sc);

        /*
         * 1、连接数据库:通过format(“jdbc”)的方式说明SparkSQL操作的数据来源是通过JDBC获得,JDBC后端
         * 一般都是数据库,eg、MySQL; 传递相关DB链接信息
         */
        DataFrameReader reader = sqlContext.read().format("jdbc");
        reader.option("url", "jdbc:mysql://112.74.21.122:3306/hive");
        reader.option("driver", "com.mysql.jdbc.Driver");
        reader.option("dbtable", "spark");
        reader.option("user", "hive");
        reader.option("password", "hive");

        /*
         * 2、加载相关数据
         */
        DataFrame sparkDF = reader.load();
        reader.option("dbtable", "hadoop");
        DataFrame hadoopDF = reader.load();

        /*
         * 3、用Spark core组织待处理的数据:这里以进行join操作(DataFrame转换成 RDD后进行)为例
         */
        JavaPairRDD<String, Tuple2<Integer, Integer>> resultRDD = sparkDF.javaRDD().mapToPair(new PairFunction<Row, String,Integer>() {
            private static final long serialVersionUID = 1L;
            @Override
            public Tuple2<String,Integer> call(Row row) throws Exception {
                return new Tuple2<String, Integer>(String.valueOf(row.getAs("name")), (Integer) row.getAs("age"));
            }
        }).join(hadoopDF.javaRDD().mapToPair(new PairFunction<Row,String,Integer>() {
            private static final long serialVersionUID = 1L;
            @Override
            public Tuple2<String,Integer> call(Row row) throws Exception {
                return new Tuple2<String, Integer>(String.valueOf(row.getAs("name")), (Integer)row.getAs("score"));
            }
        }));

        /*
         * 4、将组织好的数据交给 DataFrame 做业务处理 - 可以利用 Spark SQL 、Core、ML等进行复杂的操作!!!
         */
        // 获取 JavaRDD<Row>
        JavaRDD<Row> resultRowRDD = resultRDD.map(new Function<Tuple2<String,Tuple2<Integer,Integer>>, Row>() {
            private static final long serialVersionUID = 1L;
            @Override
            public Row call(Tuple2<String, Tuple2<Integer, Integer>> tuple) throws Exception {
                return RowFactory.create(tuple._1,tuple._2._1,tuple._2._2);
            }
        });
        //构建StructType,用于最后DataFrame元数据的描述
        List<StructField> fields = new ArrayList<StructField>();
        fields.add(DataTypes.createStructField("name", DataTypes.StringType, true));
        fields.add(DataTypes.createStructField("age", DataTypes.IntegerType, true));
        fields.add(DataTypes.createStructField("score", DataTypes.IntegerType, true));
        StructType  type = DataTypes.createStructType(fields);

        DataFrame personsDF = sqlContext.createDataFrame(resultRowRDD, type);

        // 具体业务处理 - 这里只是简单的 show 一下
        System.out.println("========================业务处理开始:ML,图计算等工具处理=================");
        System.out.println("==== start showing ====");
        personsDF.show();
        System.out.println("========================业务处理结束:ML,图计算等工具处理=================");

        /*
         * 5、保存处理后的数据:可以存放到hive,db等数据仓库中
         */
        personsDF.javaRDD().foreachPartition(new VoidFunction<Iterator<Row>>() {
            private static final long serialVersionUID = 1L;
            @Override
            public void call(Iterator<Row> iterator) throws SQLException 
            {
                Connection conn =  null;
                StringBuilder sql = new StringBuilder("INSERT INTO dfperson VALUES ( ");
                while(iterator.hasNext())
                {
                    Row row = iterator.next();
                    sql.append(String.valueOf(row.getAs("name"))).append(",").append(row.getInt(1)).append(",").append(row.getInt(2));
                }
                sql.append(")");
                try
                {
                    conn = DriverManager.getConnection("jdbc:mysql://112.74.21.122:3306/hive", "hive", "hive");
                     boolean flag = conn.createStatement().execute(sql.toString());
                } 
                catch (SQLException e) 
                {
                    e.printStackTrace();
                }
                finally
                {
                    if(null != conn) conn.close(); 
                }
            }
        });
    }
}
  • 四.SparkSQL JDBC 2 ThriftServer

package cool.pengych.spark.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author pengyucheng
 * 通过JDBC访问Thrift Server,进而访问Spark SQL,进而访问Hive
 *
 */
public class SparkSQLJDBC2ThriftServer
{
    public static void main(String[] args) throws ClassNotFoundException, SQLException
    {
        String sql = "select name from people wher age = ? ";
        Class.forName("org.apache.hive.jdbc.HiveDriver");
        Connection conn = DriverManager.getConnection("jdbc:hive2://localhost:10000/default?hive.server2.transport.mode=http;hive.server2.thrift.http.path=cliservice",
                "root","");
        conn.prepareStatement(sql);
        PreparedStatement preparedStatement = conn.prepareStatement(sql);
        preparedStatement.setInt(0, 27);
        ResultSet rs = preparedStatement.executeQuery();
        while(rs.next())
        {
            System.out.println(rs.getString(1));
        }

        conn.close();
    }

}
  • 五.SparkSQL 2 Parquet

package cool.pengych.spark.sql;

import java.util.List;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.DataFrame;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SQLContext;

/**
 * Spark SQL操作 Parquet 格式的文件内容
 * @author pengyucheng
 *
 */
public class SparkSQLParquet
{
    public static void main(String[] args) {
        /*
         * 创建SQLContext
         */
        SparkConf conf = new SparkConf().setMaster("local[*]").setAppName("SparkSQLParquet");
        JavaSparkContext jsc = new JavaSparkContext(conf);
        SQLContext sqlContext = new SQLContext(jsc);

        /*
         * 注册成为临时表以供后续SQL查询操作
         */
        DataFrame df = sqlContext.read().parquet("file:///home/hadoop/spark-1.6.0-bin-hadoop2.6/examples/src/main/resources/users.parquet");
        df.registerTempTable("users");

        /*
         * 进行数据的多维度分析
         */
        DataFrame result = sqlContext.sql("select name from users");
        JavaRDD<String> strs = result.javaRDD().map(new Function<Row, String>() {
            @Override
            public String call(Row row) throws Exception {
                return "The name is :"+row.getAs("name");
            }
        });

        /*
         * 对结果进行处理
         */
        List<String> listRow = strs.collect();
        for (String row : listRow) {
            System.out.println(row);
        }
    }

}

总结

用蓬勃的生命力战胜人性的悲剧性!package cool.pengych.spark.sql;

原文参考:https://blog.csdn.net/pengych_321/article/details/51557449

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark SQL是Apache Spark中的一个模块,它提供了一种基于结构化数据的编程接口。Spark SQL可以让用户使用SQL语句来查询数据,也可以让用户使用DataFrame API来进行数据处理和分析。Spark SQL支持多种数据源,包括Hive、JSON、Parquet等。Spark SQL还提供了一些高级功能,如支持用户自定义函数、支持分布式机器学习算法等。Spark SQL的目标是让用户能够方便地使用Spark进行数据处理和分析,同时提供高性能和可扩展性。 ### 回答2: Spark SQL是一个基于Spark平台的关系型数据处理引擎,它支持使用SQL语句和数据框架操作数据,可以轻松处理结构化和半结构化的数据。它可以从多个数据源中读取数据,包括Hive、JSON、Parquet、ORC等。通过Spark SQL,用户可以方便地使用SQL查询语言来分析和处理数据,大大降低了开发和组织数据流的难度。 Spark SQL主要有两种执行模式:SQL查询和DataFrame操作。其中SQL查询基于HiveSQL语法解析器,支持HiveQL中的大多数语言特性(如UDF、窗口函数等)。在执行计划生成时,Spark SQL采用了Spark的计算引擎,支持各种Spark算子的优化,以便最大程度地提高查询性能。 另一种操作模式是使用DataFrame API,它可以灵活地进行数据转换和处理,并提供了类似于SQL的语法。与SQL查询不同,DataFrame API通过静态检查和编译器优化来避免由SQL查询引起的语法错误和潜在性能问题。 除了这两种基本的操作模式外,Spark SQL还提供了一些高级特性,如嵌套查询、表和视图、共享变量等。这些特性扩展了Spark SQL的功能,使得它可以更加灵活地进行数据处理和查询。 Spark SQLSpark的重要组成部分,它在数据存储和处理方面提供了很多便利。通过最大程度地利用Spark引擎的优势,Spark SQL能够处理海量数据,并将其转换为有用的信息。这使得Spark SQL成为实现数据分析、机器学习和人工智能的重要工具之一。 ### 回答3: Spark SQL是一种基于Spark平台的数据处理引擎,它提供了高度优化的查询引擎和优秀的支持SQL语句的API。它允许用户使用SQL语句查询来处理大规模数据集,同时仍然支持复杂数据类型和计算。Spark SQL支持数据源,包括Parquet,Avro,JSON等一系列结构化的和半结构化的数据源Spark SQL在历史上是一个单独的模块,在Spark 2.0之后,它已经成为Spark的核心组件之一,可以直接在Spark核心API中使用,包括作为一个RDD库或DataFrame/DataSet的API。 Spark SQL的优点如下: 1. 它可以向受过传统SQL培训的用户展示更高级别,更强大的API。 2. 它提供数据集和RDD的良好互操作性。Spark SQL可以通过未被优化的RDD/DataSet API访问同一数据。 3. 它支持Spark的执行引擎以加速查询处理。 使用Spark SQL的时候,可以根据需要选择编程语言,如Scala,Java,Python,SQL等。在Spark核心API中,Spark SQL提供了两种API来处理结构化数据: 1. DataFrame API:DataFrame是具有许多操纵数据的功能的分布式数据集,类似于数据库中的表。 2. Dataset API:Dataset是Scala和Java API,它是类型安全的,并且提供与RDD API相同的API,但比RDD具有更好的性能和可读性。 Spark SQLSpark生态系统中重要的组成部分之一。在处理大规模数据时,使用Spark SQL可以方便地利用Spark的强大功能,提高处理效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值