Spark SQL筆記整理(一):Spark SQL總體背景介紹

基本概述

一、Spark 1.0版本之後,Spark官方推出了Spark SQL。其實最先使用的,都是Hadoop本身的Hive查詢引擎;好比MR2,咱們底層都是運行的MR2模型,底層都是基於Hive的查詢引擎。sql

二、後來Spark提供了Shark;再後來Shark被淘汰(Shark制約了Spark SQL的總體發展),推出了Spark SQL。Shark的性能比Hive就要高出一個數量級,而Spark SQL的性能又比Shark高出一個數量級。數據庫

三、SparkSQL的前身是Shark,給熟悉RDBMS但又不理解MapReduce的技術人員提供快速上手的工具,Hive應運而生,它是當時惟一運行在Hadoop上的SQL-on-Hadoop工具。可是MapReduce計算過程當中大量的中間磁盤落地過程消耗了大量的I/O,下降的運行效率,爲了提升SQL-on-Hadoop的效率,大量的SQL-on-Hadoop工具開始產生,其中表現較爲突出的是:express

MapR的Drill
Cloudera的Impala
Shark

四、可是Hive有個致命的缺陷,就是它的底層基於MR2,而MR2的shuffle又是基於磁盤的,所以致使Hive的性能異常低下。常常出現複雜的SQL ETL,要運行數個小時,甚至數十個小時的狀況。數組

五、Spark推出了Shark,Shark與Hive實際上仍是緊密關聯的,Shark底層不少東西仍是依賴於Hive,可是修改了內存管理、物理計劃、執行三個模塊,底層使用Spark的基於內存的計算模型,從而讓性能比Hive提高了數倍到上百倍。性能優化

Spark SQL特色

一、可是,隨着Spark的發展,對於野心勃勃的Spark團隊來講,Shark對於Hive的太多依賴(如採用Hive的語法解析器、查詢優化器等等),制約了Spark的One Stack Rule Them All的既定方針,制約了Spark各個組件的相互集成,因此提出了SparkSQL項目。SparkSQL拋棄原有Shark的代碼,汲取了Shark的一些優勢,如內存列存儲(In-Memory Columnar Storage)、Hive兼容性等,從新開發了SparkSQL代碼;因爲擺脫了對Hive的依賴性,SparkSQL不管在數據兼容、性能優化、組件擴展方面都獲得了極大的方便,真可謂「退一步,海闊天空」。工具

二、Spark SQL的特色oop

1)、支持多種數據源:Hive、RDD、Parquet、JSON、JDBC等。性能

2)、多種性能優化技術:in-memory columnar storage、byte-code generation、cost model動態評估等。優化

3)、組件擴展性:對於SQL的語法解析器、分析器以及優化器,用戶均可以本身從新開發,而且動態擴展。編碼

數據兼容方面 不但兼容Hive,還能夠從RDD、parquet文件、JSON文件中獲取數據,將來版本甚至支持獲取RDBMS數據以及cassandra等NOSQL數據;

性能優化方面 除了採起In-Memory Columnar Storage、byte-code generation等優化技術外、將會引進Cost Model對查詢進行動態評估、獲取最佳物理計劃等等;

組件擴展方面 不管是SQL的語法解析器、分析器仍是優化器均可以從新定義,進行擴展。

2014年6月1日Shark項目和SparkSQL項目的主持人Reynold Xin宣佈:中止對Shark的開發,團隊將全部資源放SparkSQL項目上,至此,Shark的發展畫上了句話,但也所以發展出兩個直線:SparkSQL和Hive on Spark。

Spark SQL筆記整理(一):Spark SQL總體背景介紹

其中SparkSQL做爲Spark生態的一員繼續發展,而再也不受限於Hive,只是兼容Hive;而Hive on Spark是一個Hive的發展計劃,該計劃將Spark做爲Hive的底層引擎之一,也就是說,Hive將再也不受限於一個引擎,能夠採用Map-Reduce、Tez、Spark等引擎。

Spark SQL性能

Shark的出現,使得SQL-on-Hadoop的性能比Hive有了10-100倍的提升:

Spark SQL筆記整理(一):Spark SQL總體背景介紹

那麼,擺脫了Hive的限制,SparkSQL的性能又有怎麼樣的表現呢?雖然沒有Shark相對於Hive那樣矚目地性能提高,但也表現得很是優異:

Spark SQL筆記整理(一):Spark SQL總體背景介紹

Spark SQL性能優化技術簡介

SparkSQL的表數據在內存中存儲不是採用原生態的JVM對象存儲方式,而是採用內存列存儲,以下圖所示:

Spark SQL筆記整理(一):Spark SQL總體背景介紹

內存列存儲(in-memory columnar storage)

一、該存儲方式不管在空間佔用量和讀取吞吐率上都佔有很大優點。

對於原生態的JVM對象存儲方式,每一個對象一般要增長12-16字節的額外開銷,對於一個270MB的數據,使用這種方式讀入內存,要使用970MB左右的內存空間(一般是2~5倍於原生數據空間);另外,使用這種方式,每一個數據記錄產生一個JVM對象,若是是大小爲200B的數據記錄,32G的堆棧將產生1.6億個對象,這麼多的對象,對於GC來講,可能要消耗幾分鐘的時間來處理(JVM的垃圾收集時間與堆棧中的對象數量呈線性相關)。顯然這種內存存儲方式對於基於內存計算的Spark來講,很昂貴也負擔不起。

​ 二、對於內存列存儲來講,將全部原生數據類型的列採用原生數組來存儲,將Hive支持的複雜數據類型(如array、map等)先序化後並接成一個字節數組來存儲。這樣,每一個列建立一個JVM對象,從而致使能夠快速的GC和緊湊的數據存儲;額外的,還可使用低廉CPU開銷的高效壓縮方法(如字典編碼、行長度編碼等壓縮方法)下降內存開銷;更有趣的是,對於分析查詢中頻繁使用的聚合特定列,性能會獲得很大的提升,緣由就是這些列的數據放在一塊兒,更容易讀入內存進行計算。

在數據庫查詢中有一個昂貴的操做是查詢語句中的表達式,主要是因爲JVM的內存模型引發的。

字節碼生成技術(byte-code generation)

Spark SQL在其catalyst模塊的expressions中增長了codegen模塊,對於SQL語句中的計算表達式,好比select num + num from t這種的sql,就可使用動態字節碼生成技術來優化其性能。

Scala代碼編寫的優化

另外,SparkSQL在使用Scala編寫代碼的時候,儘可能避免低效的、容易GC的代碼;儘管增長了編寫代碼的難度,但對於用戶來講,仍是使用統一的接口,沒受到使用上的困難。

 

 

原文連接:http://blog.51cto.com/xpleaf/2113927

相關文章
相關標籤/搜索