當前位置:首頁 » 編程語言 » sparksql內核剖析微盤pdf
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

sparksql內核剖析微盤pdf

發布時間: 2023-02-11 19:53:06

『壹』 可能是全網最詳細的 Spark sql Aggregate 源碼剖析

縱觀 Spark Sql 源碼,聚合的實現是其中較為復雜的部分,本文希望能以例子結合流程圖的方式來說清楚整個過程。這里僅關注 Aggregate 在物理執行計劃相關的內容,之前的 parse、analyze 及 optimize 階段暫不做分析。在 Spark Sql 中,有一個專門的 Aggregation strategy 用來處理聚合,我們先來看看這個策略。

本文暫不討論 distinct Aggregate 的實現(有興趣的可以看看另一篇博文 https://www.jianshu.com/p/77e0a70db8cd ),我們來看看 AggUtils#planAggregateWithoutDistinct 是如何生成聚合的物理執行計劃的

創建聚合分為兩個階段:

AggregateExpression 共有以下幾種 mode:

Q:是否支持使用 hash based agg 是如何判斷的?

摘自我另一篇文章: https://www.jianshu.com/p/77e0a70db8cd

為了說明最常用也是最復雜的的 hash based agg,本小節暫時將示例 sql 改為

這樣就能進入 HashAggregateExec 的分支

構造函數主要工作就是對 groupingExpressions、aggregateExpressions、aggregateAttributes、resultExpressions 進行了初始化

在 enable code gen 的情況下,會調用 HashAggregateExec#inputRDDs 來生成 RDD,為了分析 HashAggregateExec 是如何生成 RDD 的,我們設置 spark.sql.codegen.wholeStage 為 false 來 disable code gen,這樣就會調用 HashAggregateExec#doExecute 來生成 RDD,如下:

可以看到,關鍵的部分就是根據 child.execute() 生成的 RDD 的每一個 partition 的迭代器轉化生成一個新的 TungstenAggregationIterator ,即 HashAggregateExec 生成的 RDD 的各個 partition。由於 TungstenAggregationIterator 涉及內容非常多,我們單開一大節來進行介紹。

此迭代器:

註:UnsafeKVExternalSorter 的實現可以參考:

UnsafeRow 是 InternalRow(表示一行記錄) 的 unsafe 實現,由原始內存(byte array)而不是 Java 對象支持,由三個區域組成:

使用 UnsafeRow 的收益:

構造函數的主要流程已在上圖中說明,需要注意的是:當內存不足時(畢竟每個 grouping 對應的 agg buffer 直接佔用內存,如果 grouping 非常多,或者 agg buffer 較大,容易出現內存用盡)會從 hash based aggregate 切換為 sort based aggregate(會 spill 數據到磁碟),後文會進行詳述。先來看看最關鍵的 processInputs 方法的實現

上圖中,需要注意的是:hashMap 中 get 一個 groupingKey 對應的 agg buffer 時,若已經存在該 buffer 則直接返回;若不存在,嘗試申請內存新建一個:

上圖中,用於真正處理一條 row 的 AggregationIterator#processRow 還需進一步展開分析。在此之前,我們先來看看 AggregateFunction 的分類

AggregateFunction 可以分為 DeclarativeAggregate 和 ImperativeAggregate 兩大類,具體的聚合函數均為這兩類的子類。

DeclarativeAggregate 是一類直接由 Catalyst 中的 Expressions 構成的聚合函數,主要邏輯通過調用 4 個表達式完成,分別是:

我們再次以容易理解的 Count 來舉例說明:

通常來講,實現一個基於 Expressions 的 DeclarativeAggregate 函數包含以下幾個重要的組成部分:

再來看看 AggregationIterator#processRow

AggregationIterator#processRow 會調用

生成用於處理一行數據(row)的函數

說白了 processRow 生成了函數才是直接用來接受一條 input row 來更新對應的 agg buffer,具體是根據 mode 及 aggExpression 中的 aggFunction 的類型調用其 updateExpressions 或 mergeExpressions 方法:

比如,對於 aggFunction 為 DeclarativeAggregate 類型的 Partial 下的 Count 來說就是調用其 updateExpressions 方法,即:

對於 Final 的 Count 來說就是調用其 mergeExpressions 方法,即:

對於 aggFunction 為 ImperativeAggregate 類型的 Partial 下的 Collect 來說就是調用其 update 方法,即:

對於 Final 的 Collect 來說就是調用其 merge 方法,即:

我們都知道,讀取一個迭代器的數據,是要不斷調用 hasNext 方法進行 check 是否還有數據,當該方法返回 true 的時候再調用 next 方法取得下一條數據。所以要知道如何讀取 TungstenAggregationIterator 的數據,就得分析其這兩個方法。

分為兩種情況,分別是:

Agg 的實現確實復雜,本文雖然篇幅已經很長,但還有很多方面沒有 cover 到,但基本最核心、最復雜的點都詳細介紹了,如果對於未 cover 的部分有興趣,請自行閱讀源碼進行分析~

『貳』 Spark Sql 源碼剖析(二): TreeNode

使用 object CurrentOrigin 為 TreeNodes 提供一個可以查找上下文的地方,比如當前正在解析哪行 code。

object CurrentOrigin 主要包含一個 private val value = new ThreadLocal[Origin]() ,目前 CurrentOrigin 僅在 parser 中使用,在 visit 每個節點的時候都會使用,記錄當前 parse 的節點是哪行哪列

另外,從 value 是 ThreadLocal 類型可以看出,在 Spark SQL 中,parse sql 時都是在單獨的 thread 里進行的(不同的 sql 不同的 thread)

返回該節點的 seq of children,children 是不可變的。有三種情況:

查找第一個符合 f 條件(比如某個類型的)的 TreeNode,先序遍歷。

將函數 f 遞歸應用於節點及其子節點

與 foreach 不同的是,foreach 先應用於 parent,再應用與 child;而 foreachUp 是先應用於 child 再應用與 parent

調用 foreach,foreach 中應用的函數是 ret += f(_) ,最終返回一個 seq,包含將 f 通過 foreach 方式應用於所有節點並 add 到 ret。其中 f 本身是 BaseType => A 類型

原理與 map 一致,只是 f 變成了 BaseType => TraversableOnce[A]

PartialFunction#lift :將 partial func 轉換為一個返回 Option 結果的函數。將 pf 函數應用於符合 pf 定義的節點(即 pf.lift(node)返回的 Option 不是 None )並都 add 到 ret = new collection.mutable.ArrayBuffer[B] 以 Seq 形式返回

以 Seq 的形式返回 tree 的所有葉子節點

def collectFirst[B](pf: PartialFunction[BaseType, B]): Option[B] :注意,因為可能沒有符合 pf 定義的節點,所有返回的 Option 可能是 None

相當於 proctIterator.map(f).toArray ,即對於 proctIterator 每個元素執行 f 然後將 ret 組成一個 arr 返回

注意:TreeNode 沒有實現 Proct 相關方法,都由其子類自行實現

使用 new children 替換並返回該節點的拷貝。該方法會對 proctElement 每個元素進行模式匹配,根據節點類型及一定規則進行替換。

調用 transformDown

rule: PartialFunction[BaseType, BaseType]

返回 f 應用於所有子節點(非遞歸,一般將遞歸操作放在調用該函數的地方)後該節點的 。其內部的原理是調用 mapProctIterator,對每一個 proctElement(i) 進行各種模式匹配,若能匹配上某個再根據一定規則進行轉換,核心匹配轉換如下:

以上都是適用於有 children 的 node,如果是 children 為 null 的 node 直接返回

反射生成節點副本

返回該類型 TreeNode 的 name,默認為 class name;注意,會移除物理操作的 Exec$ 前綴

所有應該以該節點內嵌套樹表示的 nodes,比如,可以被用來表示 sub-queries

(children ++ innerChildren).toSet[TreeNode[_]]

主要用於互動式 debug,返回該 tree 指定下標的節點,num 可以在 numberedTreeString 找到。最終調用的

我的博客即將搬運同步至騰訊雲+社區,邀請大家一同入駐: https://cloud.tencent.com/developer/support-plan?invite_code=x2lzoxh4s5hi

『叄』 大數據專業主要學什麼

大數據專業
全稱:數據科學與大數據技術,強調交叉學科特點,以大數據分析為核心,以統計學、計算機科學和數學為三大基礎支撐性學科,培養面向多層次應用需求的復合型人才。
開設課程:
數學分析、高等代數、普通物理數學與信息科學概論、數據結構、數據科學導論、程序設計導論、程序設計實踐、離散數學、概率與統計、演算法分析與設計、數據計算智能、資料庫系統概論、計算機系統基礎、並行體系結構與編程、非結構化大數據分析等。

『肆』 大數據分析應該掌握哪些基礎知識

Java基礎語法

· 分支結構if/switch

· 循環結構for/while/do while

· 方法聲明和調用

· 方法重載

· 數組的使用

· 命令行參數、可變參數

IDEA

· IDEA常用設置、常用快捷鍵

· 自定義模板

· 關聯Tomcat

· Web項目案例實操

面向對象編程

· 封裝、繼承、多態、構造器、包

· 異常處理機制

· 抽象類、介面、內部類

· 常有基礎API、集合List/Set/Map

· 泛型、線程的創建和啟動

· 深入集合源碼分析、常見數據結構解析

· 線程的安全、同步和通信、IO流體系

· 反射、類的載入機制、網路編程

Java8/9/10/11新特性

· Lambda表達式、方法引用

· 構造器引用、StreamAPI

· jShell(JShell)命令

· 介面的私有方法、Optional加強

· 局部變數的類型推斷

· 更簡化的編譯運行程序等

MySQL

· DML語言、DDL語言、DCL語言

· 分組查詢、Join查詢、子查詢、Union查詢、函數

· 流程式控制制語句、事務的特點、事務的隔離級別等

JDBC

· 使用JDBC完成資料庫增刪改查操作

· 批處理的操作

· 資料庫連接池的原理及應用

· 常見資料庫連接池C3P0、DBCP、Druid等

Maven

· Maven環境搭建

· 本地倉庫&中央倉庫

· 創建Web工程

· 自動部署

· 持續繼承

· 持續部署

Linux

· VI/VIM編輯器

· 系統管理操作&遠程登錄

· 常用命令

· 軟體包管理&企業真題

Shell編程

· 自定義變數與特殊變數

· 運算符

· 條件判斷

· 流程式控制制

· 系統函數&自定義函數

· 常用工具命令

· 面試真題

Hadoop

· Hadoop生態介紹

· Hadoop運行模式

· 源碼編譯

· HDFS文件系統底層詳解

· DN&NN工作機制

· HDFS的API操作

· MapRece框架原理

· 數據壓縮

· Yarn工作機制

· MapRece案例詳解

· Hadoop參數調優

· HDFS存儲多目錄

· 多磁碟數據均衡

· LZO壓縮

· Hadoop基準測試

Zookeeper

· Zookeeper數據結果

· 內部原理

· 選舉機制

· Stat結構體

· 監聽器

· 分布式安裝部署

· API操作

· 實戰案例

· 面試真題

· 啟動停止腳本

HA+新特性

· HDFS-HA集群配置

Hive

· Hive架構原理

· 安裝部署

· 遠程連接

· 常見命令及基本數據類型

· DML數據操作

· 查詢語句

· Join&排序

· 分桶&函數

· 壓縮&存儲

· 企業級調優

· 實戰案例

· 面試真題

Flume

· Flume架構

· Agent內部原理

· 事務

· 安裝部署

· 實戰案例

· 自定義Source

· 自定義Sink

· Ganglia監控

Kafka

· 消息隊列

· Kafka架構

· 集群部署

· 命令行操作

· 工作流程分析

· 分區分配策略

· 數據寫入流程

· 存儲策略

· 高階API

· 低級API

· 攔截器

· 監控

· 高可靠性存儲

· 數據可靠性和持久性保證

· ISR機制

· Kafka壓測

· 機器數量計算

· 分區數計算

· 啟動停止腳本

DataX

· 安裝

· 原理

· 數據一致性

· 空值處理

· LZO壓縮處理

Scala

· Scala基礎入門

· 函數式編程

· 數據結構

· 面向對象編程

· 模式匹配

· 高階函數

· 特質

· 註解&類型參數

· 隱式轉換

· 高級類型

· 案例實操

Spark Core

· 安裝部署

· RDD概述

· 編程模型

· 持久化&檢查點機制

· DAG

· 運算元詳解

· RDD編程進階

· 累加器&廣播變數

Spark SQL

· SparkSQL

· DataFrame

· DataSet

· 自定義UDF&UDAF函數

Spark Streaming

· SparkStreaming

· 背壓機制原理

· Receiver和Direct模式原理

· Window原理及案例實操

· 7x24 不間斷運行&性能考量

Spark內核&優化

· 內核源碼詳解

· 優化詳解

Hbase

· Hbase原理及架構

· 數據讀寫流程

· API使用

· 與Hive和Sqoop集成

· 企業級調優

Presto

· Presto的安裝部署

· 使用Presto執行數倉項目的即席查詢模塊

Ranger2.0

· 許可權管理工具Ranger的安裝和使用

Azkaban3.0

· 任務調度工具Azkaban3.0的安裝部署

· 使用Azkaban進行項目任務調度,實現電話郵件報警

Kylin3.0

· Kylin的安裝部署

· Kylin核心思想

· 使用Kylin對接數據源構建模型

Atlas2.0

· 元數據管理工具Atlas的安裝部署

Zabbix

· 集群監控工具Zabbix的安裝部署

DolphinScheler

· 任務調度工具DolphinScheler的安裝部署

· 實現數倉項目任務的自動化調度、配置郵件報警

Superset

· 使用SuperSet對數倉項目的計算結果進行可視化展示

Echarts

· 使用Echarts對數倉項目的計算結果進行可視化展示

Redis

· Redis安裝部署

· 五大數據類型

· 總體配置

· 持久化

· 事務

· 發布訂閱

· 主從復制

Canal

· 使用Canal實時監控MySQL數據變化採集至實時項目

Flink

· 運行時架構

· 數據源Source

· Window API

· Water Mark

· 狀態編程

· CEP復雜事件處理

Flink SQL

· Flink SQL和Table API詳細解讀

Flink 內核

· Flink內核源碼講解

· 經典面試題講解

Git&GitHub

· 安裝配置

· 本地庫搭建

· 基本操作

· 工作流

· 集中式

ClickHouse

· ClickHouse的安裝部署

· 讀寫機制

· 數據類型

· 執行引擎

DataV

· 使用DataV對實時項目需求計算結果進行可視化展示

sugar

· 結合Springboot對接網路sugar實現數據可視化大屏展示

Maxwell

· 使用Maxwell實時監控MySQL數據變化採集至實時項目

ElasticSearch

· ElasticSearch索引基本操作、案例實操

Kibana

· 通過Kibana配置可視化分析

Springboot

· 利用Springboot開發可視化介面程序

『伍』 《深入理解SPARK核心思想與源碼分析》epub下載在線閱讀,求百度網盤雲資源

《深入理解SPARK》(耿嘉安)電子書網盤下載免費在線閱讀

資源鏈接:

鏈接:https://pan..com/s/1x42N8QDPGv5-KPMDdZ4krA

提取碼:oeso

書名:深入理解SPARK

作者:耿嘉安

豆瓣評分:7.2

出版社:機械工業出版社

出版年份:2016-1-1

頁數:469

內容簡介:

《深入理解SPARK:核心思想與源碼分析》結合大量圖和示例,對Spark的架構、部署模式和工作模塊的設計理念、實現源碼與使用技巧進行了深入的剖析與解讀。

《深入理解SPARK:核心思想與源碼分析》一書對Spark1.2.0版本的源代碼進行了全面而深入的分析,旨在為Spark的優化、定製和擴展提供原理性的指導。阿里巴巴集團專家鼎力推薦、阿里巴巴資深Java開發和大數據專家撰寫。

本書分為三篇:

准備篇(第1~2章),介紹了Spark的環境搭建、設計理念與基本架構,幫助讀者了解一些背景知識。

核心設計篇(第3~7章),著重講解SparkContext的初始化、存儲體系、任務提交與執行、計算引擎及部署模式的原理和源碼分析。通過這部分的內容,讀者可以通過源碼剖析更加深入理解Spark的核心設計與實現,以便在實際使用中能夠快速解決線上問題並對性能進行調優。

擴展篇(第8~11章),主要講解基於Spark核心的各種擴展及應用,包括SQL處理引擎、Hive處理、流式計算框架Spark Streaming、圖計算框架GraphX、機器學習庫MLlib等內容。通過閱讀這部分內容,讀者可以擴展實際項目中對Spark的應用場景,讓Spark煥發活力。

作者簡介:

耿嘉安,10年IT行業相關經驗。就職於阿里巴巴商家業務事業部,任資深Java工程師,專注於開源和大數據領域,目前與小夥伴們基於ODPS構建阿里的大數據商業解決方案——御膳房。在大量的工作實踐中,對J2EE、JVM、Tomcat、Spring、Hadoop、Spark、MySQL、Redis都有深入研究,尤其喜歡剖析開源項目的源碼實現。早期從事J2EE企業級應用開發,對Java相關技術有獨到見解。業余時間喜歡研究中國古代歷史,古詩詞,旅遊,足球等。

『陸』 《大數據Spark企業級實戰》pdf下載在線閱讀全文,求百度網盤雲資源

《大數據Spark企業級實戰》網路網盤pdf最新全集下載:
鏈接:https://pan..com/s/1ZKawITVbG7MADTW0Q-b4jw

?pwd=sr0q 提取碼:sr0q
簡介:《大數據Spark企業級實戰》詳細解析了企業級Spark開發所需的幾乎所有技術內容,涵蓋Spark的架構設計、Spark的集群搭建、Spark內核的解析、Spark SQL、MLLib、GraphX、Spark Streaming、Tachyon、SparkR、Spark多語言編程

『柒』 Spark SQL(十):Hive On Spark

Hive是目前大數據領域,事實上的SQL標准。其底層默認是基於MapRece實現的,但是由於MapRece速度實在比較慢,因此這幾年,陸續出來了新的SQL查詢引擎,包括Spark SQL,Hive On Tez,Hive On Spark等。

Spark SQL與Hive On Spark是不一樣的。Spark SQL是Spark自己研發出來的針對各種數據源,包括Hive、JSON、Parquet、JDBC、RDD等都可以執行查詢的,一套基於Spark計算引擎的查詢引擎。因此它是Spark的一個項目,只不過提供了針對Hive執行查詢的工功能而已,適合在一些使用Spark技術棧的大數據應用類系統中使用。

而Hive On Spark,是Hive的一個項目,它是將Spark作為底層的查詢引擎(不通過MapRece作為唯一的查詢引擎)。Hive On Spark,只適用於Hive,在可預見的未來,很有可能Hive默認的底層引擎就從MapRece切換為Spark了;適合於將原有的Hive數據倉庫以及數據統計分析替換為Spark引擎,作為全公司通用的大數據統計分析引擎。

Hive On Spark做了一些優化:
1、Map Join
Spark SQL默認對join是支持使用broadcast機制將小表廣播到各個節點上,以進行join的。但是問題是,這會給Driver和Worker帶來很大的內存開銷。因為廣播的數據要一直保留在Driver內存中。所以目前採取的是,類似乎MapRece的Distributed Cache機制,即提高HDFS replica factor的復制因子,以讓數據在每個計算節點上都有一個備份,從而可以在本地進行數據讀取。

2、Cache Table
對於某些需要對一張表執行多次操作的場景,Hive On Spark內部做了優化,即將要多次操作的表cache到內存中,以便於提升性能。但是這里要注意,並不是對所有的情況都會自動進行cache。所以說,Hive On Spark還有很多不完善的地方。

Hive QL語句 =>
語法分析 => AST =>
生成邏輯執行計劃 => Operator Tree =>
優化邏輯執行計劃 => Optimized Operator Tree =>
生成物理執行計劃 => Task Tree =>
優化物理執行計劃 => Optimized Task Tree =>
執行優化後的Optimized Task Tree

『捌』 2022-02-26-Spark-45(性能調優通用SQL調優)

RDD 的核心痛點是優化空間有限,它指的是 RDD 高階運算元中封裝的函數對於 Spark 來說完全透明,因此 Spark 對於計算邏輯的優化無從下手。相比 RDD,DataFrame 是攜帶 Schema 的分布式數據集,只能封裝結構化數據。DataFrame 的運算元大多數都是普通的標量函數,以消費數據列為主。但是,DataFrame 更弱的表示能力和表達能力,反而為 Spark 引擎的內核優化打開了全新的空間。根據 DataFrame 簡單的標量運算元和明確的 Schema 定義,藉助 Catalyst 優化器和 Tungsten,Spark SQL 有能力在運行時,構建起一套端到端的優化機制。這套機制運用啟發式的規則與策略和運行時的執行信息,將原本次優、甚至是低效的查詢計劃轉換為高效的執行計劃,從而提升端到端的執行性能

這里的 Cache 指的就是我們常說的分布式數據緩存。想要對數據進行緩存,你可以調用 DataFrame 的.cache 或.persist,或是在 SQL 語句中使用「cache table」關鍵字。Cache Manager 其實很簡單,它的主要職責是維護與緩存有關的信息。具體來說,Cache Manager 維護了一個 Mapping 映射字典,字典的 Key 是邏輯計劃,Value 是對應的 Cache 元信息。當 Catalyst 嘗試對邏輯計劃做優化時,會先嘗試對 Cache Manager 查找,看看當前的邏輯計劃或是邏輯計劃分支,是否已經被記錄在 Cache Manager 的字典里。如果在字典中可以查到當前計劃或是分支,Catalyst 就用 InMemoryRelation 節點來替換整個計劃或是計劃的一部分,從而充分利用已有的緩存數據做優化。

從 Spark Plan 到 Physical Plan 的轉換,需要幾組叫做 Preparation Rules 的規則。這些規則堅守最後一班崗,負責生成 Physical Plan。那麼,這些規則都是什麼,它們都做了哪些事情呢?

AQE 是 Spark SQL 的一種動態優化機制,在運行時,每當 Shuffle Map 階段執行完畢,AQE 都會結合這個階段的統計信息,基於既定的規則動態地調整、修正尚未執行的邏輯計劃和物理計劃,來完成對原始查詢語句的運行時優化。

DemoteBroadcastHashJoin 規則的作用,是把 Shuffle Joins 降級為 Broadcast Joins。需要注意的是,這個規則僅適用於 Shuffle Sort Merge Join 這種關聯機制,其他機制如 Shuffle Hash Join、Shuffle Nested Loop Join 都不支持。

在 Rece 階段,當 Rece Task 從全網把數據分片拉回,AQE 按照分區編號的順序,依次把小於目標尺寸的分區合並在一起

在 Rece 階段,當 Rece Task 所需處理的分區尺寸大於一定閾值時,利用 OptimizeSkewedJoin 策略,AQE 會把大分區拆成多個小分區。

相比於謂詞下推,分區剪裁往往能更好地提升磁碟訪問的 I/O 效率。謂詞下推操作往往是根據文件注腳中的統計信息完成對文件的過濾,過濾效果取決於文件中內容的「純度」。分區剪裁則不同,它的分區表可以把包含不同內容的文件,隔離到不同的文件系統目錄下。這樣一來,包含分區鍵的過濾條件能夠以文件系統目錄為粒度對磁碟文件進行過濾,從而大幅提升磁碟訪問的 I/O 效率。

動態分區剪裁運作的背後邏輯,是把維度表中的過濾條件,通過關聯關系傳導到事實表,來完成事實表的優化。在數據關聯的場景中,開發者要想利用好動態分區剪裁特性,需要注意 3 點:

NLJ 是採用「嵌套循環」的方式來實現關聯的。也就是說,NLJ 會使用內、外兩個嵌套的 for 循環依次掃描外表和內表中的數據記錄,判斷關聯條件是否滿足

SMJ 的思路是先排序、再歸並。具體來說,就是參與 Join 的兩張表先分別按照 Join Key 做升序排序。然後,SMJ 會使用兩個獨立的游標對排好序的兩張表完成歸並關聯。

先用 Hash Key 取代 Join Keys,再清除內表冗餘數據。Hash Key 實際上是 Join Keys 拼接之後的哈希值。既然存在哈希運算,我們就必須要考慮哈希沖突的問題。

AQE 允許 Spark SQL 在運行時動態地調整 Join 策略。我們剛好可以利用這個特性,把最初制定的 SMJ 策略轉化為 BHJ 策略

當參與 Join 的兩張表尺寸相差懸殊且小表數據分布均勻的時候,SHJ 往往比 SMJ 的執行效率更高。這種情況下,我們不妨使用 Join Hints 來強制 Spark SQL 去選擇 SHJ 策略進行關聯計算

先把一個復雜任務拆解成多個簡單任務,再合並多個簡單任務的計算結果。首先,我們要根據兩張表的尺寸大小區分出外表和內表。一般來說,內表是尺寸較小的那一方。然後,我們人為地在內表上添加過濾條件,把內表劃分為多個不重復的完整子集。接著,我們讓外表依次與這些子集做關聯,得到部分計算結果。最後,再用 Union 操作把所有的部分結果合並到一起,得到完整的計算結果,這就是端到端的關聯計算。

「分而治之」中一個關鍵的環節就是內表拆分,我們要求每一個子表的尺寸相對均勻,且都小到可以放進廣播變數。拆分的關鍵在於拆分列的選取,為了讓子表足夠小,拆分列的基數(Cardinality)要足夠大才行。

對於外表參與的每一個子關聯,在邏輯上,我們完全可以只掃描那些與內表子表相關的外表數據,並不需要每次都掃描外表的全量數據。

有了 AQE 的自動傾斜處理特性,在應對數據傾斜問題的時候,我們確實能夠大幅節省開發成本。不過,天下沒有免費的午餐,AQE 的傾斜處理是以 Task 為粒度的,這意味著原本 Executors 之間的負載傾斜並沒有得到根本改善

「兩階段 Shuffle」

「兩階段 Shuffle」指的是,通過「加鹽、Shuffle、關聯、聚合」與「去鹽化、Shuffle、聚合」這兩個階段的計算過程,在不破壞原有關聯關系的前提下,在集群范圍內以 Executors 為粒度平衡計算負載 。