Spark:saveAsTable解析
说一下默认的配置saveAsTable
方法会以parquet文件的形式存储数据,但是由于spark和hive使用的parquet标准不一致(对decimal
类型存储的时候,具体和精度有关如DecimalType(10,2)
会报错而DecimalType(38,18)
并不会报错)。
所以如果DataFrame里有DecimalType
类型,会出现用spark存的表spark可以读取,hive客户端读取报错的问题。在spark中可以通过配置来更改spark使用的parquet存储标准(但是hive不能配置),所以在用spark saveAsTable
时最好都加上此配置:
.config("spark.sql.parquet.writeLegacyFormat", true)
saveAsTable
会利用hive API将Dataset持久化为表,其中表的元数据默认用derby存了一个数据库中,表的数据会存在spark.sql.warehouse.dir
变量的文件夹下。
元数据的存储默认用derby数据库。
使用derby数据库:
#下载
wget -O ../db-derby-10.12.1.1-bin.tar.gz
#解压
tar -zxf db-derby-10.12.1.1-bin.tar.gz -C derby
#配置环境变量
export DERBY_HOME=/root/derby
export PATH=$PATH:$DERBY_HOME/bin
export CLASSPATH=$CLASSPATH:$DERBY_HOME/lib
#启动交互模式
ij
#指定默认协议
ij> PROTOCOL 'jdbc:derby:';
#连接数据库,
ij> connect '/root/dir/metastore_db';
#若没指定默认协议,则用:
ij> connect 'jdbc:derby:/root/dir/metastore_db';
#若不存在数据库则创建用:
ij> connect 'jdbc:derby:/root/dir/metastore_db;create=true';
#显示表
ij> show tables;
#执行语句
ij> select * from table_a;
#退出
ij> exit;
若用java连接,需在classpath里加入jar包,为上面解压后的derby/lib/derby.jar(此版本为3.1MB):
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.DatabaseMetaData;
public class Main {
private static final String driver = "org.apache.derby.jdbc.EmbeddedDriver" ;
private static final String url = "jdbc:derby:test;create=true" ;
static void printSQLException(SQLException se) {
while(se != null) {
System.out.print("SQLException: State: " + se.getSQLState());
System.out.println("Severity: " + se.getErrorCode());
System.out.println(se.getMessage());
se = se.getNextException();
}
}
static void printSQLWarning(SQLWarning sw) {
while(sw != null) {
System.out.print("SQLWarning: State=" + sw.getSQLState()) ;
System.out.println(", Severity = " + sw.getErrorCode()) ;
System.out.println(sw.getMessage());
sw = sw.getNextWarning();
}
}
public static void main(String[] args) {
Connection con = null ;
DatabaseMetaData dbmd = null ;
try {
Class.forName(driver) ;
con = DriverManager.getConnection(url);
SQLWarning swarn = con. getWarnings() ;
if(swarn != null){
printSQLWarning(swarn) ;
}
dbmd = con.getMetaData() ;
System.out.println("\n----------------------------------------------------") ;
System.out.println("Database Name = " + dbmd.getDatabaseProductName()) ;
System.out.println("Database Version = " + dbmd.getDatabaseProductVersion()) ;
System.out.println("Driver Name = " + dbmd.getDriverName()) ;
System.out.println("Driver Version = " + dbmd.getDriverVersion()) ;
System.out.println("Database URL = " + dbmd.getURL()) ;
System.out.println("----------------------------------------------------") ;
} catch (SQLException se) {
printSQLException(se) ;
} catch(ClassNotFoundException e){
System.out.println("JDBC Driver " + driver + " not found in CLASSPATH") ;
}
finally {
if(con != null){
try{
con.close() ;
} catch(SQLException se){
printSQLException(se) ;
}
}
}
}
}
通过derby可以查看hive元数据表,如下:
ij> select * from DBS;
ij> select * from SEQUENCE_TABLE;
ij> select * from SERDES;
ij> select * from SERDE_PARAMS;
ij> select * from TABLE_PARAMS;
ij> select * from VERSION;