1,DataFrame是一个将数据格式化为列形式的分布式容器,类似于一个关系型数据库表.
编程入口:SQLContext
2,SQLContext由SparkContext对象创建
也可创建一个功能更加全面的HiveContext对象,HiveContext是SQLContext的子类,从API中可以看出HiveContext extends SQLContext,所以能用SQLContext的地方也能用HiveContext
3,使用HiveContext可以使用更加复杂的HiveQL语句,可以使用Hive UDF,可以从Hive表中读取数据.
4,创建DataFrames
可以从已有的RDD, Hive表或者数据源创建DataFrame
sqlContext.read方法返回一个DataFrameReader对象,该对象有jdbc,json,parquet,load等方法从数据源加载数据,生成一个DataFrame对象的功能
DataFrame对象的show方法,显示DataFrame中的前20条记录
write方法返回一个DataFrameWriter对象,可以将数据写入输出中
sqlContext.sql方法,执行sql语句,并返回一个DataFrame对象
5,将已有RDD转化为DataFrame,有两种方法
(1)使用reflection将RDD转化成DataFrame
Spark SQL的接口支持自动将一个包含case类的RDD转化成DataFrame.case类中定义了table表结构.case类的参数被反射机制读入,并作为表的列名.case类也可以使用数组等复杂的数据结构.
(2)通过一个编程接口构建表结构,然后应用与已有RDD
在case表无法预先定义好的情况下,可以使用这种方法构建DataFrame.
a,从原始RDD创建一个行RDD(RDD of Rows)
b,创建一个与a步骤中相匹配的schema,使用StructType
c,使用SQLContext的createDataFrame方法将schema转化成DataFrame
6,数据源(Data Sources)
通过DataFrame,Spark SQL支持在多种数据上进行操作.一个DataFrame能够被当做普通RDD进行操作,也可以注册为一个临时表.
sqlContext.read方法返回一个DataFrameReader对象,该对象有多种方法可以将数据源加载到程序中.
7,数据保存模式(Save Modes)
指定不同的保存模式,将对数据的写出进行不同的操作.注意这些保存模式没有实现锁功能,也不能自动实现,所以,当有多个用户向同一位置写出时会不安全.
SaveMode.ErrorIfExists(默认) 如果数据已经存在,抛异常
SaveMode.Append 如果数据以存在,追加到最后
SaveMode.Overwrite 如果数据以存在,覆盖(先删除,)
SaveMode.Ignore 如果数据已存在,则不保存,类似于(create table if not exists)
8,持久化到表中(Saving to Persistent Tables)
使用HiveContext时,使用saveAsTable命令DataFrames也可以保存为持久化的表.
9,Parquet文件
Parquet是基于列存储的数据结构.
(1)parquet文件加载
sqlContext.read.parquet("people.parquet");(也可用load方法加载)
(2)parquet文件输出
val people:RDD[Person], people.write.parquet("people.parquet")
10,表分区(Partition discovery)
某个分区如下所示:
将path/to/table路径传递给SQLContext.read.parquet或者SQLContext.read.load,SparkSQL会自动的从路径中提取分区信息.
最终的DataFrame会变成如下形式:
11,结构的合并(Schema merging)
ProtocolBuffer,Avro,Thrifs和Parquet都支持结构自动调整.用户可以以一个简单的表结构开始,慢慢的增加一些其他字段.这样,最终用户会得到很大不同但是内在又有关联的Parquet文件.在SparkSQL中,这些Parquet数据源可以被自动检测并且将这些结构进行合并.
val df1 = ....
df1.write.parquet("data/test_table/key=1")
val df2 = ....
df2.write.parquet("data/test_table/key=2")
val df3 = sqlContext.read.parquet("data/test_table")
12,Parquet的相关配置(Configuration)
Parquet数据的配置可以使用SQLContext的setConf方法进行设置,或者使用SQL中的命令,SET key=value
spark.sql.parquet.binaryAsString | false | 一些其他的parquet系统,当把该parquet schema写出时,不区分二进制数据和string字符串.这个属性告诉Spark SQL把二进制数据解析成string字符串 |
spark.sql.parquet.int96AsTimestamp | true | 其他parquet系统将timestamp存储为INT96型.Spark同样将timestamp保存为INT96,不失精度. |
spark.sql.parquet.cacheMetadata | true | 启用缓存一些parquet schema metadata的功能,提高访问静态数据的速度 |
spark.sql.parquet.compression.codec | gzip | 设置parquet文件写出的压缩方式,包括:uncompressed,snappy,gzip, lzo |
spark.sql.parquet.filterPushdown | false | Turn on Parquet filter pushdown optimization. This feature is turned off by default because of a known bug in Parquet 1.6.0rc3 (PARQUET-136). However, if your table doesn't contain any nullable string or binary columns, it's still safe to turn this feature on. |
spark.sql.hive.convertMetastoreParquet | true | 设置为false时,Spark SQL会使用Hive SerDe来处理paquet表,而不是使用the built in support |
13,JSON数据集(JSON Datasets)
使用SQLContext.read.json()方法载入一个String RDD或者JSON文件
需要注意的是,这里所谓的json文件不是传统的JSON文件.每一行必须包含一个分离的,自包含的标准的JSON对象.所以,一个多行的JSON文件无法读入.
也就是说,这里载入的json文件如果有多行的话,每一行都必须是一个标准的JSON文件.
如spark example自带的people.json文件:
{"name":"Michael"}
{"name":"Andy", "age":30}
{"name":"Justin", "age":19}
{"name":"Andy", "age":30}
{"name":"Justin", "age":19}
14,Hive表(Hive Tables)
Spark SQL同样支持从Hive中读取和写入数据.然而,由于Hive需要依赖很多其他的系统,在默认的Spark assembly中并不包含对Hive的支持.可以在编译Spark时添加参数-Phive和-Phive-thriftserver.
初始化一个HiveContext对象,该对象继承自SQLContext,并且增加了在MetaStore中的表的查询功能和使用HiveQL查询的功能.及时没有安装Hive也可以使用HiveContext.如果没有hive-site.xml文件,则会自动的在当前文件夹中创建metastore_db和warehouse
val sqlContext = new HiveContext(sc)
与不同版本的Hive Metastore交互(Interacting with Different Versions of Hive Metastore)
15,使用JDBC连接其他的数据(JDBC To Other Databases)
实现该功能需要使用到JdbcRDD类.
程序运行时,需要包含JDBC驱动jar包.如果要在spark-shell中使用jdbc功能,需要按如下方式启动spark-shell:
SPARK_CLASSPATH=postgresql-9.3-1102-jdbc41.jar bin/spark-shell
val jdbcDF = sqlContext.load("jdbc", Map("url"->"jdbc:postgresql:dbserver","dbtable"->"schema.tablename"))
各参数含义:
url | JDBC URL |
dbtable | 将要读入的表 |
driver | The class name of the JDBC driver needed to connect to this URL. This class will be loaded on the master and workers before running an JDBC commands to allow the driver to register itself with the JDBC subsystem. |
partitionColumn, lowerBound, upperBound, numPartitions |
These options must all be specified if any of them is specified. They describe how to partition the table when reading in parallel from multiple workers. partitionColumn must
be a numeric column from the table in question. Notice that lowerBound and upperBound are
just used to decide the partition stride, not for filtering the rows in table. So all rows in the table will be partitioned and returned. |
(1)注意事项(Troubleshooting)
a)JDBC驱动class必须在所有executors上可访问.这样实现的一个方法是修改所有worker节点上的compute_classpath.sh文件,使之包含这个driver JARs
b)有些数据库,例如H2,会将所有names转化成大写,所以需要在Spark SQL中使用upper case来对应这些names
15,性能调优(Performance Tuning)
(1)数据缓存到内存中(Caching Data In Memory)
调用sqlContext.cacheTable("tableName")或者dataFrame.cache()将Spark SQL数据缓存到内存中.将内存中的表移除,sqlContext.uncacheTable("tableName")
使用SQLContext对象的setConf方法或者使用SQL SET key=value命令
spark.sql.inMemoryColumnarStorage.compressed | true | Spark SQL会基于数据的信息自动为每一个字段选择压缩方式 |
spark.sql.inMemoryColumnarStorage.batchSize | 1000 | 控制columnar 缓存的大小.参数越大效率越高,但是可能会导致内存溢出 |
(2)其他可选配置(Other Configuration Options)
16,分布式SQL引擎(Distributed SQL Engine)
Spark SQL也可以当做一个分布式的查询引擎,使用JDBC/ODBC或者命令行(command-line)的方式
(1)运行Thrift JDBC/ODBC服务
待完善......
(2)运行Spark SQL CLI
可以使用Spark SQL命令行模式运行相关的HiveQL语句,在本地模式(local mode)中使用.所以,Spark SQL CLI不能与Thrift JDBC服务建立连接.
./bin/spark-sql
17,升级指南(Migration Guide)
(1)从Spark SQL 1.3升级到1.4
待完善.......
(2)从Spark SQL 1.0-1.2 升级到1.3
待完善.......
18, Shark用户升级
待完善.......
19,与Hive兼容(Compatibility with Apache Hive)
Spark SQL可与Hive的Metastore,SerDes(序列化与反序列化)和UDF(用户自定义函数)相兼容,spark-1.4基于Hive 0.12.0和0.13.1
(1)在已有Hive Warehouses中安装
Spark SQL Thrift JDBC server 是开箱即用(out of box)的,即不需要修改现有的Hive Metastore,也不需要更改表数据或分区的安放位置.
(2)支持的Spark特性(Supported Hive Features)
a),Hive查询语句
包括,SELECT, GROUP BY, ORDER BY, CLUSTER BY, SORT BY
b),所有的Hive操作,包括
关系型操作:
=
, ⇔
, ==
, <>
, <
, >
, >=
, <=等
算术操作:+,-,*,/,%等
逻辑操作:AND, &&, OR, ||等
复杂的类型构造(type constructors)
数学方法:sign, ln, cos等
字符串函数:instr, length, printf等
c),用户自定义函数(UDF)
d),用户自定义聚合函数(UDAF)
e),用户自定义序列化与反序列化(SerDes)
f),Joins
JOIN, {LEFT|RIGHT|FULL} OUTER JOIN, LEFT SEMI JOIN, CROSS JOIN
g),Unions
h),子查询
select col from (select a + b as col from t1) t2
i),抽样(Sampling)
j),Explain
k),表分区
l),视图
m),所有Hive DDL语句,包括
CREATE TABLE, CREATE TABLE AS SELECT, ALTER TABLE
n),大部分Hive数据类型
TINYINT, SMALLINT, INT, BIGINT, BOOLEAN, FLOAT, DOUBLE, STRING, BINARY, TIMESTAMP, DATE, ARRAY<>, MAP<>, STRUCT<>
(3)不支持的hive函数
待完善..........
20,数据类型(Data Types)
Spark SQL和DataFrames支持以下数据类型:
a)数字类型
ByteType,1个字节
ShortType,2个字节
IntegerType,4个字节
LongType,8个字节
FloatType,4个字节
DoubleType,8个字节
DecimalType,
b)字符串类型
StringType
c)二进制位类型
BinaryType
d)布尔类型
BooleanType
e) 时间类型
TimestampType
DateType
f)复杂类型
ArrayType(elementType, containsNull)
MapType(keyType, valueType, valueContainsNull)
StructType(fields)