Spark-SQL 使用SQL處理結(jié)構(gòu)化數(shù)據(jù)模塊(七) 概念及原理介紹

技術(shù)背景

  • 優(yōu)缺點(diǎn)分析:
    SQL: 擅長數(shù)據(jù)分析和通過簡(jiǎn)單語法表示查詢,表達(dá)清晰,適用于結(jié)構(gòu)化數(shù)據(jù)
    API: 擅長過程式處理和算法性處理,操作粒度細(xì),適用于非結(jié)構(gòu)化數(shù)據(jù)和半結(jié)構(gòu)化數(shù)據(jù)
  • 在spark出現(xiàn)之前,一個(gè)工具一向只支持SQL或者API處理,很難統(tǒng)一化
  • 在sparksql出現(xiàn)之前,大數(shù)據(jù)結(jié)構(gòu)化數(shù)據(jù)分析一般只能使用hive,hive的缺點(diǎn)導(dǎo)致越來越不適合業(yè)務(wù)場(chǎng)景
  • Databricks公司采用上層使用hive的sql語法,下層將hive的物理執(zhí)行計(jì)劃mr替代為sparkcore來實(shí)現(xiàn)的一款名為shark的工具
  • shark的執(zhí)行計(jì)劃生成嚴(yán)重依賴于hive,想要增加新的優(yōu)化非常困難,hive是進(jìn)程級(jí)別的并行,spark是線程級(jí)別的的并行,hive中很多線程不安全的代碼不適用于spark,隨著hive的維護(hù)升級(jí),shark必須也做一次相應(yīng)的維護(hù)升級(jí),維護(hù)和優(yōu)化困難
  • 2014年databricks公司宣布停止shark的開發(fā),將重心放在sparksql之上

設(shè)計(jì)目的

解決基于spark使用sql分析海量結(jié)構(gòu)化數(shù)據(jù)的業(yè)務(wù)場(chǎng)景

設(shè)計(jì)思想

sparkSql將執(zhí)行計(jì)劃和優(yōu)化交給優(yōu)化器catalyst,替代之前shark的執(zhí)行計(jì)劃和優(yōu)化是hive的
hive底層將sql轉(zhuǎn)換為mr程序,sparksql底層將sql轉(zhuǎn)換為RDD

技術(shù)本質(zhì)

sparkSQl內(nèi)置了一套簡(jiǎn)單的SQL解析器,可以不使用HQL
還引入了一套dataframe這樣的DSL api,完全可以不依賴任何hive的組件
spark1.6之后,又使用dataset api來統(tǒng)一和結(jié)合sql的訪問和命令式api的使用,
開發(fā)者可以使用sql來進(jìn)行查詢并篩選數(shù)據(jù),然后使用API來進(jìn)行探索式分析

核心特性

  • 易整合:
    sparksql無縫的將sql和api整合在一起,意味著你可以在程序中使用你所熟悉的sql或者api來進(jìn)行操作
  • 統(tǒng)一的數(shù)據(jù)訪問格式:
    sparksql統(tǒng)一了數(shù)據(jù)訪問格式,意味著你可以用同一種方式訪問任意數(shù)據(jù)源
  • 兼容hive:
    sparksql與hivesql語法兼容,以及sparksql可以訪問hive倉庫
  • 標(biāo)準(zhǔn)的數(shù)據(jù)連接:
    可以通過jdbc或odbc來連接

重點(diǎn)概念

DataFrame

  • 背景:
    DataFrame的前身是SchemaRDD,從Spark 1.3.0開始SchemaRDD更名為DataFrame,并不再直接繼承自RDD,而是自己實(shí)現(xiàn)了RDD的絕大多數(shù)功能
  • 概念:
    一種帶有Schema元信息的以RDD為基礎(chǔ)的分布式數(shù)據(jù)集,類似于傳統(tǒng)的二維表格
  • 意義:
    1. 記錄了數(shù)據(jù)集的Schema元信息,可將非結(jié)構(gòu)化或半結(jié)構(gòu)化數(shù)據(jù)變?yōu)榻Y(jié)構(gòu)化數(shù)據(jù),供于sql操作
    2. DataFrame也是懶執(zhí)行的。性能上比RDD要高,主要原因:優(yōu)化的執(zhí)行計(jì)劃:查詢計(jì)劃通過Spark catalyst optimiser進(jìn)行優(yōu)化,邏輯查詢計(jì)劃優(yōu)化就是一個(gè)利用基于關(guān)系代數(shù)的等價(jià)變換,將高成本的操作替換為低成本操作的過程。
  • 使用
    1. 從結(jié)構(gòu)化或半結(jié)構(gòu)化數(shù)據(jù)源創(chuàng)建
    2. 從RDD進(jìn)行轉(zhuǎn)換
    3. 從HiveTable進(jìn)行查詢返回

DataSet

  • 背景:
    DataSet是在Spark1.6中添加的新的接口。
  • 概念:
    一種帶有Schema元信息的以RDD為基礎(chǔ)的具有強(qiáng)類型的分布式數(shù)據(jù)集
  • 意義:
    1. 用戶友好的API風(fēng)格,既具有類型安全檢查也具有Dataframe的查詢優(yōu)化特性。
    2. Dataset支持編解碼器,當(dāng)需要訪問非堆上的數(shù)據(jù)時(shí)可以避免反序列化整個(gè)對(duì)象,提高了效率。
    3. 與DataFrame相比,保存了類型信息,是強(qiáng)類型的,提供了編譯時(shí)類型檢查,調(diào)用Dataset的方法先會(huì)生成邏輯計(jì)劃,然后被spark的優(yōu)化器進(jìn)行優(yōu)化,最終生成物理計(jì)劃,然后提交到集群中運(yùn)行!
  1. 使用:

Row

  • 概念:
    可以理解為一種javaBean,可以隨意的更改屬性
  • 使用:
    1. 通過構(gòu)造器構(gòu)建
    2. 調(diào)用靜態(tài)方法Row.fromSeq構(gòu)建

RDD/DataFrame/DataSet對(duì)比

聯(lián)系

  1. 都是spark平臺(tái)下的彈性分布式數(shù)據(jù)集,為處理的超大型數(shù)據(jù)提供便利
  2. 都是lazy模式,只有遇到action算子時(shí)才會(huì)觸發(fā)執(zhí)行
  3. 都會(huì)根據(jù)spark的內(nèi)存情況自動(dòng)緩存運(yùn)算,即使數(shù)據(jù)量很大,也不用擔(dān)心發(fā)生OOM
  4. 都有partition概念
  5. 有共同的函數(shù),如filter,排序等
  6. 可以進(jìn)行相互轉(zhuǎn)化

區(qū)別

  1. RDD: 有泛型,沒有Schema
    1. RDD一般和sparkMLlib同時(shí)使用
    2. RDD不支持SparkSQL操作
  2. DataFrame: 沒有泛型,有Schema
    1. DataFrame每一行的類型固定為Row,每一列的值沒法直接訪問,只有通過解析才能獲取各個(gè)字段的值
    2. DataFrame和DataSet一般不與sparkMLlib同時(shí)使用
    3. DataFrame與Dataset均支持sparksql的操作,還能注冊(cè)臨時(shí)表/視圖,進(jìn)行sql語句操作
    4. DataFrame與Dataset支持一些特別方便的保存方式
  3. DataSet:有泛型有Schema
    1. DataSet和DataFrame擁有完全相同的成員函數(shù),區(qū)別只是每一行的數(shù)據(jù)類型不同
    2. DataFrame也可以叫做DataSet[Row],每一行的類型是Row,不解析,

關(guān)系

  1. RDD - T + Schema = DataFrame
  2. RDD + Schema = DataSet
  3. DataSet[Row] = DataFrame

轉(zhuǎn)化

  1. 將DS或DF轉(zhuǎn)換為RDD,只需要調(diào)用ds或df的rdd方法即可
  2. 將RDD轉(zhuǎn)換為DS或DF
    1. 使用反射: 將RDD的字段拆分封裝成為一個(gè)RDD[對(duì)象]返回,然后調(diào)用tods或todf方法
    2. 構(gòu)建schema: 將RDD的字段拆分封裝成為一個(gè)RDD[Row]類型,然后利用structType構(gòu)建一個(gè)schema,最后在使用spark.createDataFrame方法進(jìn)行拼接
  3. 將DF轉(zhuǎn)為DS,需要調(diào)用df的as方法,添加泛型,或者調(diào)用tods方法,導(dǎo)入隱式轉(zhuǎn)換
  4. 將DS轉(zhuǎn)為DF,需要調(diào)用ds的todf方法,導(dǎo)入隱式轉(zhuǎn)換

查詢方式

  • 兩種風(fēng)格
  1. SQL風(fēng)格:
    如果想使用SQL風(fēng)格的語法,需要將DataFrame注冊(cè)成表,然后調(diào)用調(diào)用sql方法
  2. DSL風(fēng)格:
    DSL是由spark提供的一個(gè)領(lǐng)域特定語言用來方便操作結(jié)構(gòu)化數(shù)據(jù),將sql中的字段映射成為對(duì)應(yīng)的方法,不需要注冊(cè)成表

自定義函數(shù)

  1. UDF:

    1. SQL風(fēng)格: sparkSession.udf.register()
    2. DSL風(fēng)格: val toUpString = udf(
      (name:String) => name.toUpperCase //將傳進(jìn)來的名字轉(zhuǎn)為大寫
      )
  2. UDAF:

    1. 繼承UserDefinedAggregateFunction方法
    2. 重寫inputSchema:輸入數(shù)據(jù)的類型,bufferSchema:產(chǎn)生中間結(jié)果的數(shù)據(jù)類型,dataType:最終返回的結(jié)果類型,deterministic:確保一致性,一般用true,initialize:指定初始值,update:每有一條數(shù)據(jù)參與運(yùn)算就更新一下中間結(jié)果(update相當(dāng)于在每一個(gè)分區(qū)中的運(yùn)算),merge:全局聚合(將每個(gè)分區(qū)的結(jié)果進(jìn)行聚合),evaluate:計(jì)算最終的結(jié)果
  3. UDTF:

    1. 目的:
      既顯示聚集前的數(shù)據(jù),又顯示聚集后的數(shù)據(jù),在每一行的最后一列添加聚合函數(shù)的結(jié)果。
    2. 意義:
      聚合函數(shù)是將多行變成一行;開窗函數(shù)是將一行變成多行;
    3. 使用:
      1. OVER 關(guān)鍵字表示把聚合函數(shù)當(dāng)成聚合開窗函數(shù)而不是聚合函數(shù)。SQL標(biāo)準(zhǔn)允許將所有聚合函數(shù)用做聚合開窗函數(shù)。
      2. 排序開窗函數(shù),同hive

Spark on Hive

SparkSQL整合Hive其實(shí)就是讓SparkSQL去加載Hive 的元數(shù)據(jù)庫,然后通過SparkSQL執(zhí)行引擎去操作Hive表

數(shù)據(jù)源

普通文本、json、parquet、csv、jdbc,odbc

應(yīng)用場(chǎng)景

  1. RDD主要用于處理非結(jié)構(gòu)化數(shù)據(jù)、半結(jié)構(gòu)化數(shù)據(jù)、結(jié)構(gòu)化
    1. SparkSQL主要用于處理結(jié)構(gòu)化數(shù)據(jù)(較為規(guī)范的半結(jié)構(gòu)化數(shù)據(jù)也可以處理)
  2. SparkSQL 相較于 RDD 的優(yōu)勢(shì)在哪?
    1. SparkSQL 提供了更好的外部數(shù)據(jù)源讀寫支持
    2. SparkSQL 提供了直接訪問列的能力
  3. SQL替代API的意義在于哪?
    1. sql處理結(jié)構(gòu)化數(shù)據(jù)的能力比api處理性能更好,基于列訪問,這是主要的應(yīng)用意義
    2. sql可以簡(jiǎn)化開發(fā),學(xué)習(xí)成本低,適用于數(shù)據(jù)分析人員,api適用于開發(fā)者
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容