spark sql在scala中使用的兩種方式,以及其他一些知識點

hgs19921112發表於2018-10-15
package hgs.spark.sql
import org.apache.spark.SparkConf
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.SQLImplicits
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.Row
//第一種方法建立dataframe
object SqlTest1 {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("sqltest1").setMaster("local")
    val context = new SparkContext(conf)
    val sqlContext = new SQLContext(context)
    
    val rdd = context.textFile("d:\\person",1)
    val rdd2 = rdd.map(x=>{val t = x.split(" ");person(t(0).toInt,t(1),t(2).toInt)})
    //第一種方法建立dataframe,在這裡需要匯入隱式轉換
    import sqlContext.implicits._      
    val persondf = rdd2.toDF()  
    //這個方法在2.1.0裡面被廢除
    //persondf.registerTempTable("person")
    //使用該函式代替
    persondf.createOrReplaceTempView("person")
    val result = sqlContext.sql("select * from person order by age desc")
    //列印查詢的結果
    result.show()
    //或者將結果儲存到檔案
    result.write.json("d://personselect")
   
    context.stop()
  }
}
case class person(id:Int,name:String,age:Int)
//第二種方法建立dataframe
//3.1.2.	透過StructType直接指定Schema
object SqlTest2{
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("sqltest2").setMaster("local")
    val context = new SparkContext(conf)
    val sqlContext = new SQLContext(context)
    
    val rdd = context.textFile("d:\\person",1)
    
    //第一種方法建立dataframe,在這裡需要匯入隱式轉換
    //建立schema,即一個對映關係   
    val personShcema = StructType(
    List(
        //下面為一個列的描述,分別為 列名,資料型別,是否為空
        StructField("id",IntegerType,true),
        StructField("name",StringType,true),
        StructField("age",IntegerType,true)
     )    
    )
    
    val rdd2 = rdd.map(x=>{val t = x.split(" ");Row(t(0).toInt,t(1),t(2).toInt)})
    //透過這種方式建立dataframe
    val persondf = sqlContext.createDataFrame(rdd2, personShcema)
    //將dataframe對映為一個臨時的表
    persondf.createOrReplaceTempView("person")
    //查詢資料展示
    sqlContext.sql("select * from person order by age desc").show()
    context.stop()
/*  查詢出的資料
 *  +---+----+---+
    | id|name|age|
    +---+----+---+
    |  1| hgs| 26|
    |  3|  zz| 25|
    |  2|  wd| 24|
    |  4|  cm| 24|
    +---+----+---+
    */
    
  }
}
一些筆記:
checkpoint:
	將rdd中間過程持久化到hdfs上面,如果某個rdd失敗,則從hdfs回覆,這樣代價較小
	sc.setCheckpointDir("hdfs dir or other fs dir "),建議將RDD cache之後再
	checkpoin這樣將減少一次運算直接從記憶體中將RDD進行checkpoin
	但是這樣之前依賴的RDD也會被丟棄
RDD Objects構建DAG--->DAGScheduler(TaskSet(每個Task在每個excutor上&&切分stage,並提價stage))
    ------>TaskScheduler(Task&&提交task,)------>Worker	(執行task)
stage:根據依賴關係區分stage,當遇到一個寬依賴(節點之間交換資料)的時候劃分一個stage
	其中窄依賴:父RDD的分割槽資料只傳向一個子RDD分割槽,而寬依賴則是父RDD的分割槽資料會傳向多個子RDD的或者多個分割槽
	
spark SQL:處理結構化的資料
	DataFrames:與RDD類似,DataFrame也是一個分散式資料容器。然而DataFrame更像傳統資料庫的二維表格,
		除了資料以外,還記錄資料的結構資訊,即schema。同時,與Hive類似,DataFrame也支援
		巢狀資料型別(struct、array和map)。從API易用性的角度上 看,DataFrame API提供的是一套高層
		的關係操作,比函式式的RDD API要更加友好,門檻更低。由於與R和Pandas的DataFrame類似,
		Spark DataFrame很好地繼承了傳統單機資料分析的開發體驗
	建立DataFrame: 將資料對映為class,RDD.toDF 
	透過sql查詢,將df註冊為一個表1. df.registerTempTable("test") sqlContext.sql("select * from test").show 
								 2.透過StructType定義:StrutType(List())
hive 3.0.0 與spark
	1.將hive-site.xml hdfs-site.xml  core-site.xml複製到spark的conf資料夾下 ,將mysql驅動放到spark的jars資料夾下面
	2.在hive中的語句在spark-sql中完全適用:
		create table person(id int,name string,age int) row format delimited fields terminated by ' ';
		load data inpath 'hdfs://bigdata00:9000/person' into table person;
		select * from person;
		資料如下:
			1	hgs	26
			2	wd	24
			3	zz	25
			4	cm	24
	3.在spark-sql console互動中會列印很多的INFO級別的資訊,很煩人,解決辦法是
		在conf資料夾下:
		   mv log4j.properties.template  log4j.properties
			將log4j.rootCategory=INFO, console 修改為log4j.rootCategory=WARN, console


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31506529/viewspace-2216359/,如需轉載,請註明出處,否則將追究法律責任。

相關文章