SparkSQL编程指南之Java篇三-数据源(下)

来源:互联网 发布:数据精灵授权管理系统 编辑:程序博客网 时间:2024/05/17 01:00
4. Hive Tables

Spark SQL支持对Hive的读写操作。然而因为Hive有很多依赖包,所以这些依赖包没有包含在默认的Spark包里面。如果Hive依赖的包能在classpath找到,Spark将会自动加载它们。需要注意的是,这些Hive依赖包必须复制到所有的工作节点上,因为它们为了能够访问存储在Hive的数据,会调用Hive的序列化和反序列化(SerDes)包。Hive的配置文件hive-site.xml、core-site.xml(security配置)和hdfs-site.xml(HDFS配置)是保存在conf目录下面。

当使用Hive时,必须初始化一个支持Hive的SparkSession,用户即使没有部署一个Hive的环境仍然可以使用Hive。当没有配置hive-site.xml时,Spark会自动在当前应用目录创建metastore_db和创建由spark.sql.warehouse.dir配置的目录,如果没有配置,默认是当前应用目录下的spark-warehouse目录。注意,从Spark 2.0.0版本开始,hive-site.xml里面的hive.metastore.warehouse.dir属性已经被spark.sql.warehouse.dir替代,用于指定warehouse的默认数据路径(必须有写权限)。

import java.io.Serializable;import java.util.ArrayList;import java.util.List;import org.apache.spark.api.java.function.MapFunction;import org.apache.spark.sql.Dataset;import org.apache.spark.sql.Encoders;import org.apache.spark.sql.Row;import org.apache.spark.sql.SparkSession;public static class Record implements Serializable {  private int key;  private String value;  public int getKey() {    return key;  }  public void setKey(int key) {    this.key = key;  }  public String getValue() {    return value;  }  public void setValue(String value) {    this.value = value;  }}// warehouseLocation points to the default location for managed databases and tablesString warehouseLocation = "/spark-warehouse";// init spark session with hive supportSparkSession spark = SparkSession  .builder()  .appName("Java Spark Hive Example")  .master("local[*]")  .config("spark.sql.warehouse.dir", warehouseLocation)  .enableHiveSupport()  .getOrCreate();spark.sql("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)");spark.sql("LOAD DATA LOCAL INPATH 'examples/src/main/resources/kv1.txt' INTO TABLE src");// Queries are expressed in HiveQLspark.sql("SELECT * FROM src").show();// +---+-------+// |key|  value|// +---+-------+// |238|val_238|// | 86| val_86|// |311|val_311|// ...// only showing top 20 rows// Aggregation queries are also supported.spark.sql("SELECT COUNT(*) FROM src").show();// +--------+// |count(1)|// +--------+// |    500 |// +--------+// The results of SQL queries are themselves DataFrames and support all normal functions.Dataset<Row> sqlDF = spark.sql("SELECT key, value FROM src WHERE key < 10 ORDER BY key");// The items in DaraFrames are of type Row, which lets you to access each column by ordinal.Dataset<String> stringsDS = sqlDF.map(row -> "Key: " + row.get(0) + ", Value: " + row.get(1), Encoders.STRING());stringsDS.show();// +--------------------+// |               value|// +--------------------+// |Key: 0, Value: val_0|// |Key: 0, Value: val_0|// |Key: 0, Value: val_0|// ...// You can also use DataFrames to create temporary views within a SparkSession.List<Record> records = new ArrayList<Record>();for (int key = 1; key < 100; key++) {  Record record = new Record();  record.setKey(key);  record.setValue("val_" + key);  records.add(record);}Dataset<Row> recordsDF = spark.createDataFrame(records, Record.class);recordsDF.createOrReplaceTempView("records");// Queries can then join DataFrames data with data stored in Hive.spark.sql("SELECT * FROM records r JOIN src s ON r.key = s.key").show();// +---+------+---+------+// |key| value|key| value|// +---+------+---+------+// |  2| val_2|  2| val_2|// |  2| val_2|  2| val_2|// |  4| val_4|  4| val_4|// ...// only showing top 20 rows

* 如果使用eclipse运行上述代码的话需要添加spark-hive的jars,下面是maven的配置:

<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-hive_2.11 --><dependency><groupId>org.apache.spark</groupId><artifactId>spark-hive_2.11</artifactId><version>2.1.0</version></dependency>

否则的话会遇到下面错误:

Exception in thread "main" java.lang.IllegalArgumentException: Unable to instantiate SparkSession with Hive support because Hive classes are not found.at org.apache.spark.sql.SparkSession$Builder.enableHiveSupport(SparkSession.scala:815)at JavaSparkHiveExample.main(JavaSparkHiveExample.java:17)

4.1 与不同版本Hive Metastore的交互

Spark SQL对Hive的支持其中一个最重要的部分是与Hive metastore的交互,使得Spark SQL可以访问Hive表的元数据。从Spark 1.4.0版本开始,Spark SQL使用下面的配置可以用于查询不同版本的Hive metastores。需要注意的是,本质上Spark SQL会使用编译后的Hive 1.2.1版本的那些类来用于内部操作(serdes、UDFs、UDAFs等等)。



5. JDBC To Other Databases

Spark SQL也支持使用JDBC访问其他数据库。该功能建议使用JdbcRDD,因为返回的结果是DataFrame,它们在Spark SQL里或者与其它数据源连接的时候更容易处理。JDBC数据源因为不需要用户提供ClassTag,所以在Java或Python里更容易使用(注意,这里说的JDBC和Spark SQL里面的JDBC server是不同的,后者允许其它应用使用Spark SQL去执行查询)。

在使用之前需要在Spark的classpath里面添加指定数据库的JDBC驱动。例如要从Spark Shell连接Postgres数据库需要执行以下命令:

bin/spark-shell --driver-class-path postgresql-9.4.1207.jar --jars postgresql-9.4.1207.jar

远程数据库的表可以通过使用数据源的API加载为DataFrame或者Spark SQL临时视图。用户可以在数据源的选项里指定JDBC连接的属性,例如用于登录数据库的用户名和密码。除了用于连接的属性之外,Spark也支持以下区分大小写的选项:



// Note: JDBC loading and saving can be achieved via either the load/save or jdbc methods// Loading data from a JDBC sourceDataset<Row> jdbcDF = spark.read()  .format("jdbc")  .option("url", "jdbc:postgresql:dbserver")  .option("dbtable", "schema.tablename")  .option("user", "username")  .option("password", "password")  .load();Properties connectionProperties = new Properties();connectionProperties.put("user", "username");connectionProperties.put("password", "password");Dataset<Row> jdbcDF2 = spark.read()  .jdbc("jdbc:postgresql:dbserver", "schema.tablename", connectionProperties);// Saving data to a JDBC sourcejdbcDF.write()  .format("jdbc")  .option("url", "jdbc:postgresql:dbserver")  .option("dbtable", "schema.tablename")  .option("user", "username")  .option("password", "password")  .save();jdbcDF2.write()  .jdbc("jdbc:postgresql:dbserver", "schema.tablename", connectionProperties);

6. 两个问题及解决方法
  • 在客户端的session和所有executors中的启动类加载器必须能够加载相应的JDBC驱动类。这是因为Java的DriverManager类会执行安全检查,当打开一个连接的时候,忽略那些不能被启动类加载器加载的JDBC驱动类。其中一种方便的方法是修改所有工作节点的compute_classpath.sh,把需要的驱动jars包含进来
  • 某些数据库,例如H2,会把所有的名字转换为大写,因此在Spark SQL里面使用时也需要使用大写
* 参考Spark SQL官方链接:http://spark.apache.org/docs/latest/sql-programming-guide.html#data-sources

TO BE CONTINUED...O(∩_∩)O
1 0
原创粉丝点击