技術(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)的二維表格 - 意義:
- 記錄了數(shù)據(jù)集的Schema元信息,可將非結(jié)構(gòu)化或半結(jié)構(gòu)化數(shù)據(jù)變?yōu)榻Y(jié)構(gòu)化數(shù)據(jù),供于sql操作
- DataFrame也是懶執(zhí)行的。性能上比RDD要高,主要原因:優(yōu)化的執(zhí)行計(jì)劃:查詢計(jì)劃通過Spark catalyst optimiser進(jìn)行優(yōu)化,邏輯查詢計(jì)劃優(yōu)化就是一個(gè)利用基于關(guān)系代數(shù)的等價(jià)變換,將高成本的操作替換為低成本操作的過程。
- 使用
- 從結(jié)構(gòu)化或半結(jié)構(gòu)化數(shù)據(jù)源創(chuàng)建
- 從RDD進(jìn)行轉(zhuǎn)換
- 從HiveTable進(jìn)行查詢返回
DataSet
- 背景:
DataSet是在Spark1.6中添加的新的接口。 - 概念:
一種帶有Schema元信息的以RDD為基礎(chǔ)的具有強(qiáng)類型的分布式數(shù)據(jù)集 - 意義:
- 用戶友好的API風(fēng)格,既具有類型安全檢查也具有Dataframe的查詢優(yōu)化特性。
- Dataset支持編解碼器,當(dāng)需要訪問非堆上的數(shù)據(jù)時(shí)可以避免反序列化整個(gè)對(duì)象,提高了效率。
- 與DataFrame相比,保存了類型信息,是強(qiáng)類型的,提供了編譯時(shí)類型檢查,調(diào)用Dataset的方法先會(huì)生成邏輯計(jì)劃,然后被spark的優(yōu)化器進(jìn)行優(yōu)化,最終生成物理計(jì)劃,然后提交到集群中運(yùn)行!
- 使用:
Row
- 概念:
可以理解為一種javaBean,可以隨意的更改屬性 - 使用:
- 通過構(gòu)造器構(gòu)建
- 調(diào)用靜態(tài)方法Row.fromSeq構(gòu)建
RDD/DataFrame/DataSet對(duì)比
聯(lián)系
- 都是spark平臺(tái)下的彈性分布式數(shù)據(jù)集,為處理的超大型數(shù)據(jù)提供便利
- 都是lazy模式,只有遇到action算子時(shí)才會(huì)觸發(fā)執(zhí)行
- 都會(huì)根據(jù)spark的內(nèi)存情況自動(dòng)緩存運(yùn)算,即使數(shù)據(jù)量很大,也不用擔(dān)心發(fā)生OOM
- 都有partition概念
- 有共同的函數(shù),如filter,排序等
- 可以進(jìn)行相互轉(zhuǎn)化
區(qū)別
- RDD: 有泛型,沒有Schema
- RDD一般和sparkMLlib同時(shí)使用
- RDD不支持SparkSQL操作
- DataFrame: 沒有泛型,有Schema
- DataFrame每一行的類型固定為Row,每一列的值沒法直接訪問,只有通過解析才能獲取各個(gè)字段的值
- DataFrame和DataSet一般不與sparkMLlib同時(shí)使用
- DataFrame與Dataset均支持sparksql的操作,還能注冊(cè)臨時(shí)表/視圖,進(jìn)行sql語句操作
- DataFrame與Dataset支持一些特別方便的保存方式
- DataSet:有泛型有Schema
- DataSet和DataFrame擁有完全相同的成員函數(shù),區(qū)別只是每一行的數(shù)據(jù)類型不同
- DataFrame也可以叫做DataSet[Row],每一行的類型是Row,不解析,
關(guān)系
- RDD - T + Schema = DataFrame
- RDD + Schema = DataSet
- DataSet[Row] = DataFrame
轉(zhuǎn)化
- 將DS或DF轉(zhuǎn)換為RDD,只需要調(diào)用ds或df的rdd方法即可
- 將RDD轉(zhuǎn)換為DS或DF
- 使用反射: 將RDD的字段拆分封裝成為一個(gè)RDD[對(duì)象]返回,然后調(diào)用tods或todf方法
- 構(gòu)建schema: 將RDD的字段拆分封裝成為一個(gè)RDD[Row]類型,然后利用structType構(gòu)建一個(gè)schema,最后在使用spark.createDataFrame方法進(jìn)行拼接
- 將DF轉(zhuǎn)為DS,需要調(diào)用df的as方法,添加泛型,或者調(diào)用tods方法,導(dǎo)入隱式轉(zhuǎn)換
- 將DS轉(zhuǎn)為DF,需要調(diào)用ds的todf方法,導(dǎo)入隱式轉(zhuǎn)換
查詢方式
- 兩種風(fēng)格
- SQL風(fēng)格:
如果想使用SQL風(fēng)格的語法,需要將DataFrame注冊(cè)成表,然后調(diào)用調(diào)用sql方法 - DSL風(fēng)格:
DSL是由spark提供的一個(gè)領(lǐng)域特定語言用來方便操作結(jié)構(gòu)化數(shù)據(jù),將sql中的字段映射成為對(duì)應(yīng)的方法,不需要注冊(cè)成表
自定義函數(shù)
-
UDF:
- SQL風(fēng)格: sparkSession.udf.register()
- DSL風(fēng)格: val toUpString = udf(
(name:String) => name.toUpperCase //將傳進(jìn)來的名字轉(zhuǎn)為大寫
)
-
UDAF:
- 繼承UserDefinedAggregateFunction方法
- 重寫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é)果
-
UDTF:
- 目的:
既顯示聚集前的數(shù)據(jù),又顯示聚集后的數(shù)據(jù),在每一行的最后一列添加聚合函數(shù)的結(jié)果。 - 意義:
聚合函數(shù)是將多行變成一行;開窗函數(shù)是將一行變成多行; - 使用:
- OVER 關(guān)鍵字表示把聚合函數(shù)當(dāng)成聚合開窗函數(shù)而不是聚合函數(shù)。SQL標(biāo)準(zhǔn)允許將所有聚合函數(shù)用做聚合開窗函數(shù)。
- 排序開窗函數(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)景
- RDD主要用于處理非結(jié)構(gòu)化數(shù)據(jù)、半結(jié)構(gòu)化數(shù)據(jù)、結(jié)構(gòu)化
- SparkSQL主要用于處理結(jié)構(gòu)化數(shù)據(jù)(較為規(guī)范的半結(jié)構(gòu)化數(shù)據(jù)也可以處理)
- SparkSQL 相較于 RDD 的優(yōu)勢(shì)在哪?
- SparkSQL 提供了更好的外部數(shù)據(jù)源讀寫支持
- SparkSQL 提供了直接訪問列的能力
- SQL替代API的意義在于哪?
- sql處理結(jié)構(gòu)化數(shù)據(jù)的能力比api處理性能更好,基于列訪問,這是主要的應(yīng)用意義
- sql可以簡(jiǎn)化開發(fā),學(xué)習(xí)成本低,適用于數(shù)據(jù)分析人員,api適用于開發(fā)者