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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM