大數據SQL調優專題——調優切入

引入

我們都知道大數據的SQL優化,并非一蹴而就的簡單任務,而是一個涉及多個環節的復雜過程。雖然我們的專欄名字叫大數據SQL調優,但是調優并不是簡單對SQL優化,而是一個涉及多個環節的復雜過程。實際上從需求接入到最終交付,任何一個環節的都可能影響最終成果。而調優的本質并非對任務進行大規模重構,而是通過各種監控工具,排查梳理出瓶頸點在哪,并深入了解其成因以及對應需求背景,才能以最小的代價進行修改或調整。

正所謂“工欲善其事,必先利其器”。在優化過程中,無論是發現問題的根源,還是尋找最優的解決方案,合適的工具、流程和思路都至關重要。

以下將我們從數據研發日常工作的角度,來簡要介紹調優的幾個關鍵切入點。

梳理真實需求

梳理真實需求的前提是理解業務,這是數倉調優的根基。只有深入理解企業的業務流程、業務模式和業務目標,才能明確業務部門的真實需求是什么。

數據最終的目的是賦能業務、驅動業務,以此為前提,我們就需要用數據準確的展示業務現狀,為業務和分析提供數據支持。而要做到以上各點,必須了解業務痛點,理解業務流程,分析出業務場景中可能存在的問題,以及判斷各業務方的訴求是否合理、其底層的真實需求是否和表述需求一致等。

所謂理解業務,從高層視角而言,指的是了解行業的基本模式、運作的流程、供需之間如何流轉,本質就是找到不同主體之間的業務流轉關系。從底層視角看的話,則是需要清楚地知道不同表中具體字段的含義,以及相關的表有哪些,他們之間的數據關聯關系是什么等。數據是客觀存在的,而需求才是基于業務的,很多不必要的資源開銷、冗長的溝通、費盡周折的查詢優化,其實在源頭階段是可以避免的。只有了解業務,我們才有能力去甄別需求是否合理,其背后隱藏的真實需求是怎樣的。

所以對于一個合格的數據研發來說,在開發工作開始之前,就需要明確以下幾點:

1.明確需求

不要接到需求就只顧埋頭實現,在正常開發流程的需求澄清會上,不要悶頭光想著怎么實現需求,要學會多問問需求提供方或業務方究竟要做什么事情,想達到什么目的,并與業務提供需求文檔和設計文檔核對復驗,最后要記得詢問期望的結果、反饋和交付時間節點。這樣的過程才談得上是一個閉環,而不是埋頭苦干一通,最后發現需要返工,或者被業務人員全盤否定。

2.應對需求的正確思路

比如老板發現一個城市的司機接單指標下跌了,不要急著去查口徑,找數據問題,或者直接拿相關數據去做多維交叉分析,拿歷史數據波動,看同環比等。因為當數據指標出現異常時,急于從數據本身尋找答案,最后的結果可能也只是“自證清白”,并沒能找到問題根因,我們應該深入探究背后的業務邏輯。比如前面提的指標下跌的原因,可能是因為多方面的,比如高峰期剛過,或者對應城市天氣問題等,基于業務理解,去找出這些真正影響指標的答案,才是正確的思路。

3.技術棧應用儲備

大數據處理的技術棧種類繁多,它們都有各自的適用場景和局限性,也就是所謂的術業有專攻,目前也沒有出現一個能解決所有問題的銀彈。而需求方不了解也不關心底層的具體實現和局限性,所有數據研發作為其中承上啟下的重要節點,就需要有相關大數據處理技術廣度和深度的知識儲備,才能幫助或引導模糊的需求具象化、合理化。

收集相關信息

執行計劃

執行計劃(Execution Plan,也叫查詢計劃或者解釋計劃)是查詢優化的重要依據。我們可以通過EXPLAIN命令查看優化器針對指定SQL生成的邏輯執行計劃。如果要分析某條SQL的性能問題,通常需要先查看SQL的執行計劃,排查每一步SQL執行是否存在問題。

通過查看執行計劃,我們可以得到表的讀取順序、表之間的引用、表連接的順序、表連接的方式以及實際讀取文件的位置等信息。盡管不同的框架實現會導致執行計劃有所差異,但目的都是相同的。通過使用EXPLAIN關鍵字,可以模擬優化器執行SQL查詢語句,從而理解引擎是如何處理SQL語句的。這樣我們就能夠分析提交的查詢語句可能存在的性能瓶頸。

例如通過EXPLAIN命令解析HQL執行計劃去定位以下可能的瓶頸:

  • ?JOIN順序優化:優先過濾小表以減少Shuffle數據量。
  • ?數據傾斜處理:識別Hash Join中的傾斜Key。
  • ?資源分配:根據Stage耗時調整Map/Reduce并發度。

統計信息

統計信息對于查詢優化也是至關重要。前面我們有提到CBO,其本質就是依賴統計信息來選擇最優的執行計劃。

統計數據分為表級別的統計數據(如行數、大小等)和列級別的統計數據(如最大、最小值等)兩類。表或字段的統計信息有助于我們更深入地了解表中數據的分布情況,從而規避潛在的問題。例如,單表數據量過大,就可以考慮將表轉換為分區或分桶表;如果字段唯一值數量較少,在去重時就需要注意潛在的數據傾斜問題。

在Hive中,除了保存元數據庫表之外,也會保存這兩類統計信息,包括表或分區的大小、行數等信息。Hive會盡可能地在每次變更數據時更新統計信息,以確保其準確性。統計信息的主要用途在于輔助CBO制定更高效的查詢計劃,從而選擇成本最低的執行路徑。此外,當啟用配置hive.compute.query.using.stats(默認關閉)時,對于COUNT(1)、MIN、MAX等聚合查詢,引擎會直接利用統計信息快速返回結果,而無須進行實際的文件掃描操作。

在Spark中,盡管我們也使用Hive Metastore來管理庫表的元數據,并且Spark能夠兼容Hive表的讀寫操作,但Spark對于Hive統計信息的利用與Hive本身存在差異。Spark定義了一套自己的統計指標和規則體系,這也意味著由Spark引擎寫入的統計信息不會被其他引擎所利用和共享。此外,Spark在處理統計信息的寫入時比Hive更為謹慎。在默認配置下,Spark并不會在數據寫入時自動更新統計信息,這導致Hive Metastore中的統計數據可能無法準確地反映表的當前狀態。Spark主要通過org.apache.spark.sql.execution.command.CommandUtils類中的update-TableStats方法來更新表級別的統計信息,感興趣小伙伴可以深入看看其實現原理。其核心就是,如果處理的是非分區表,它會遞歸遍歷表存儲路徑下的所有文件,并對每個文件的大小進行求和。如果處理的是分區表,它會默認使用listPartitions方法獲取所有分區的路徑,然后并行計算每個分區的大小。最終,該方法只會更新表級別的spark.sql.statistics.totalSize屬性。對于字段級別的統計信息,只能通過執行ANALYZE TABLE...COMPUTE STATISTICS FOR COLUMNS...命令來進行計算和寫入。這個語句會記錄某個字段在整張表中的最小值、最大值等統計信息,但并不會在分區維度上進行統計。字段級別的統計信息包括平均長度(avgLen)、唯一值的數量(distinctCount)、最小值(min)、最大值(max)、最大長度(maxLen)、空值數量(nullCount)以及直方圖(histogram)。前幾個統計值的含義相對直觀,而直方圖(histogram)則較為特殊,需要在開啟spark.sql.statistics.histogram.enabled后,再運行ANALYZE命令才能生成。直方圖會將字段值的分布切分成n個百分比位(n=spark.sql.statistics.histogram.numBins,默認值為254)?,每一段內部會統計最小值、最大值和唯一值的數量。直方圖可以對高頻查詢字段建立統計快照,加速范圍查詢響應。

執行日志

執行日志記錄了數據庫的各種操作和事件,包括查詢執行時間、錯誤信息等。通過分析執行日志,可以發現頻繁執行的查詢、耗時較長的查詢以及出現錯誤的查詢。針對這些問題查詢,可以進行針對性的優化,提高數據倉庫的整體性能。

而且日志有助于保護開發人員和用戶免受應用程序和系統中大規模故障和問題的影響。由于我們無法24h實時監控查詢任務,因此當任務出現錯誤并失敗時,我們需要確定原因,此時日志的重要性就顯現出來了。日志對于程序執行的監控和問題定位至關重要。在系統設計、開發和實現的過程中,必須關注輸出的日志,這對于查詢任務的異常分析至關重要。

通常我們會分析日志中的關鍵指標:

  • ?Shuffle溢出:監控磁盤溢出次數。
  • ?GC耗時:通過日志中的GC暫停時間判斷內存配置合理性,優化堆內存分配。

分析工具

Dr.Elephant

Dr.Elephant 是一個用于分析大數據作業性能的工具。它可以幫助用戶識別性能瓶頸、優化資源使用和提高作業效率。通過 Dr.Elephant,可以收集和分析作業的執行時間、資源消耗等信息,為性能調優提供數據支持。將作業的執行日志上傳到Dr.Elephant,Dr.Elephant會生成詳細的分析報告,指出作業的性能問題,并提供優化建議。

Dr.Elephant于2016年4月由LinkedIn開源,是一個支持Hadoop和Spark的性能監控和調優工具。Dr.Elephant能自動收集所有指標,進行數據分析,并以簡單易用的方式進行呈現。與此同時,Dr.Elephant也支持對Hadoop和Spark任務進行可插拔式、配置化以及基于規則的啟發式Job性能分析,并且能根據分析結果給出合適的建議,來指導開發人員進行調優以使任務有更高效率。

火焰圖

火焰圖是一種可視化工具,可以幫助用戶直觀地了解程序的執行流程和性能瓶頸。在大數據數倉調優中,火焰圖可以用于分析查詢執行過程中的 CPU 使用率、內存分配等情況,幫助找到性能瓶頸所在。

通常的做法是,使用性能分析工具(如perf)收集程序的執行數據,生成火焰圖,通過分析火焰圖找出執行時間較長的函數或代碼段,進行優化。

火焰圖(Flame Graph)是由Linux性能優化大師Brendan Gregg發明的。和其他的性能分析方法不同,火焰圖以一個全局視野來看待時間分布,它由下向上地列出所有可能導致性能瓶頸的調用棧。

Prometheus

Prometheus 是一個開源的監控系統,廣泛應用于云計算和容器化環境中。在大數據數倉中,Prometheus 可以用于收集和監控各種指標,如 CPU 使用率、內存使用率、網絡流量等。通過監控這些指標,可以及時發現性能問題,并采取相應的措施進行優化。

通過部署Prometheus服務器和相關的Exporter,收集系統的監控數據,使用Prometheus的查詢語言(PromQL)查詢和分析數據,設置報警規則,來及時發現和處理性能問題。

Prometheus是由SoundCloud開源的監控告警解決方案,2012年開始編寫代碼,2015年開源,發展速度迅猛,社區活躍,并且被廣泛應用于各大公司中,Prometheus通過領先的開源監控解決方案為用戶的指標和告警提供了強大的技術支持。

等價重寫思想

在數據庫領域,等價重寫思想乃是一種極具價值的優化技術。其旨在對查詢表達式進行優化改寫,使得改寫后的表達式與原始查詢等價,同時在執行效率、性能或其他方面展現出更為顯著的優勢。等價重寫的核心目標在于通過巧妙地重新組織查詢結構,充分利用數據庫系統的優化策略,從而大幅降低查詢的計算成本。

盡管大數據引擎在物理實現方面與關系型數據庫存在著較大差異,然而,在設計思想以及實際應用過程中,這些差異并非十分突出。一方面,我們能夠借助引擎自身所支持的優化功能,例如基于關系代數以及利用等價變換的規則。另一方面,我們可以通過對查詢語句進行改寫,進而實現優化查詢語句的目的。

等價重寫思想是一種基于關系代數的查詢優化技術,其核心在于通過語義等價性轉換生成執行效率更高的新查詢表達式。

該技術遵循兩大原則:

  1. 數學等價性:利用關系代數的結合律、交換律、分配律等規則(如投影下推、選擇分解、外連接轉半連接),保證重寫前后的查詢結果完全一致;
  2. 執行高效性:通過重構查詢結構降低計算復雜度(如減少全表掃描)、提升索引利用率(如將LIKE 'abc%'改寫為范圍查詢)、優化分布式數據分片策略(如減少Shuffle數據量)。

典型技術場景:

  • 子查詢提升:將IN子查詢轉化為SEMI JOIN,避免嵌套循環執行(如SELECT * FROM film WHERE id IN (SELECT film_id FROM film_actor)?→?SELECT f.* FROM film f JOIN film_actor fa ON f.id=fa.film_id);
  • 謂詞下推:提前過濾無效數據(如將WHERE a>10 AND b<5分解為兩階段過濾);
  • 常量折疊:預計算靜態表達式(如WHERE a=1+1重寫為WHERE a=2)。

大數據的演化區別:

維度傳統關系型數據庫大數據引擎
優化模式自動優化為主(如CBO優化器)手動干預為主(需人工規避Shuffle瓶頸)
核心挑戰復雜SQL的索引選擇與執行計劃穩定性分布式數據傾斜與網絡傳輸成本控制
共性技術謂詞下推、常量折疊、連接順序優化分區剪枝、動態資源分配、小文件合并

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70969.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70969.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70969.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

貪心算法精品題

1.找錢問題 本題的貪心策略在于我們希望就可能的保留作用大的5元 class Solution { public:bool lemonadeChange(vector<int>& bills) {std::map<int ,int> _map;for(auto ch:bills){if(ch 5) _map[ch];else if(ch 10){if(_map[5] 0) return false;else{_m…

spring結合mybatis多租戶實現單庫分表

實現單庫分表 思路&#xff1a;student表數據量大&#xff0c;所以將其進行分表處理。一共有三個分表&#xff0c;分別是student0&#xff0c;student1&#xff0c;student2&#xff0c;在新增數據的時候&#xff0c;根據請求頭中的meta-tenant參數決定數據存在哪張表表。 數…

Ecode前后端傳值

說明 在泛微 E9 系統開發過程中&#xff0c;使用 Ecode 調用后端接口并進行傳值是極為常見且關鍵的操作。在上一篇文章中&#xff0c;我們探討了 Ecode 調用后端代碼的相關內容&#xff0c;本文將深入剖析在 Ecode 中如何向后端傳值&#xff0c;以及后端又該如何處理接收這些值…

黑馬Java面試教程_P5_微服務

系列博客目錄 文章目錄 系列博客目錄1.引言2.Spring Cloud2.1 Spring Cloud 5大組件有哪些?面試文稿 2.2 服務注冊和發現是什么意思?Spring Cloud 如何實現服務注冊發現?面試文稿 2.3 我看你之前也用過nacos、你能說下nacos與eureka的區別?面試文稿 2.4 你們項目負載均衡如…

【2025深度學習環境搭建-2】pytorch+Docker+VS Code+DevContainer搭建本地深度學習環境

上一篇文章&#xff1a;【2025深度學習環境搭建-1】在Win11上用WSL2和Docker解鎖GPU加速 先啟動Docker&#xff01;對文件內容有疑問&#xff0c;就去問AI 一、用Docker拉取pytorch鏡像&#xff0c;啟動容器&#xff0c;測試GPU docker pull pytorch/pytorch:2.5.0-cuda12.4…

Linux驅動開發實戰(一):LED控制驅動詳解

Linux驅動開發野火實戰&#xff08;一&#xff09;&#xff1a;LED控制驅動詳解 文章目錄 Linux驅動開發野火實戰&#xff08;一&#xff09;&#xff1a;LED控制驅動詳解引言一、基礎知識1.1 什么是字符設備驅動1.2 重要的數據結構read 函數write 函數open 函數release 函數 二…

Linux上用C++和GCC開發程序實現不同MySQL實例下單個Schema之間的穩定高效的數據遷移

設計一個在Linux上運行的GCC C程序&#xff0c;同時連接兩個不同的MySQL實例&#xff0c;兩個實例中分別有兩個Schema的表結構完全相同&#xff0c;復制一個實例中一個Schema里的所有表的數據到另一個實例中一個Schema里&#xff0c;使用以下快速高效的方法&#xff0c;加入異常…

Redis除了做緩存還能做什么?

Redis 除了作為高性能緩存外&#xff0c;還因其豐富的數據結構和功能&#xff0c;廣泛應用于多種場景。以下是 Redis 的十大核心用途及具體示例&#xff1a; 1. 分布式會話存儲 用途&#xff1a;存儲用戶會話信息&#xff08;如登錄狀態&#xff09;&#xff0c;實現多服務間共…

JBoltAI_SpringBoot如何區分DeepSeek R1深度思考和具體回答的內容(基于Ollama)?

當我們用Ollama運行DeepSeek R1模型&#xff0c;向它提問時&#xff0c;會發現它的回答里是有think標簽的 如果我們直接將Ollama的回復用于生產環境&#xff0c;肯定是不行的&#xff0c;對于不同的場景&#xff0c;前面輸出的一堆內容&#xff0c;可能并不需要在客戶端展示&a…

MySQL 使用 `WHERE` 子句時 `COUNT(*)`、`COUNT(1)` 和 `COUNT(column)` 的區別解析

文章目錄 1. COUNT() 函數的基本作用2. COUNT(*)、COUNT(1) 和 COUNT(column) 的詳細對比2.1 COUNT(*) —— 統計所有符合條件的行2.2 COUNT(1) —— 統計所有符合條件的行2.3 COUNT(column) —— 統計某一列非 NULL 的記錄數 3. 性能對比3.1 EXPLAIN 分析 4. 哪種方式更好&…

將DeepSeek接入vscode的N種方法

接入deepseek方法一:cline 步驟1:安裝 Visual Studio Code 后,左側導航欄上點擊擴展。 步驟2:搜索 cline,找到插件后點擊安裝。 步驟3:在大模型下拉菜單中找到deep seek,然后下面的輸入框輸入你在deepseek申請的api key,就可以用了 讓deepseek給我寫了一首關于天氣的…

AndroidManifest.xml文件的作用

AndroidManifest.xml文件在Android應用程序中扮演著至關重要的角色。它是應用程序的全局配置文件&#xff0c;提供了關于應用程序的所有必要信息&#xff0c;這些信息對于Android系統來說是至關重要的&#xff0c;因為它決定了應用程序的運行方式和權限要求&#xff0c;確保了應…

Mac本地部署Deep Seek R1

Mac本地部署Deep Seek R1 1.安裝本地部署大型語言模型的工具 ollama 官網&#xff1a;https://ollama.com/ 2.下載Deepseek R1模型 網址&#xff1a;https://ollama.com/library/deepseek-r1 根據電腦配置&#xff0c;選擇模型。 我的電腦&#xff1a;Mac M3 24G內存。 這…

React進階之前端業務Hooks庫(五)

前端業務Hooks庫 Hooks原理useStateuseEffect上述問題useState,useEffect 復用的能力練習:怎樣實現一套React過程中的hooks狀態 & 副作用Hooks原理 不能在循環中、條件判斷、子函數中調用,只能在函數最外層去調用useEffect 中,deps 為空,執行一次useState 使用: imp…

從像素到光線:現代Shader開發的范式演進與性能優化實踐

引言 在實時圖形渲染領域&#xff0c;Shader作為GPU程序的核心載體&#xff0c;其開發范式已從早期的固定功能管線演進為高度可編程的計算單元。本文通過解析關鍵技術案例&#xff0c;結合現代圖形API&#xff08;如Vulkan、Metal&#xff09;的特性&#xff0c;深入探討Shade…

(七)消息隊列-Kafka 序列化avro(傳遞)

&#xff08;七&#xff09;消息隊列-Kafka 序列化avro&#xff08;傳遞&#xff09; 客從遠方來&#xff0c;遺我雙鯉魚。呼兒烹鯉魚&#xff0c;中有尺素書。 ——佚名《飲馬長城窟行》 本文已同步CSDN、掘金平臺、知乎等多個平臺&#xff0c;圖片依然保持最初發布的水印&…

PXE批量網絡裝機與Kickstart自動化安裝工具

目錄 一、系統裝機的原理 1.1、系統裝機方式 1.2、系統安裝過程 二、PXE批量網絡裝機 2.1、PXE實現原理 2.2、搭建PXE實際案例 2.2.1、安裝必要軟件 2.2.2、搭建DHCP服務器 2.2.3、搭建TFTP服務器 2.2.4、掛載鏡像并拷貝引導文件到tftp服務啟動引導文件夾下 2.2.5、編…

【全棧開發】從0開始搭建一個圖書管理系統【一】框架搭建

【全棧開發】從0開始搭建一個圖書管理系統【一】框架搭建 前言 現在流行降本增笑&#xff0c;也就是不但每個人都要有事干不能閑著&#xff0c;更重要的是每個人都要通過報功的方式做到平日的各項工作異常飽和&#xff0c;實現1.5人的支出干2人的活計。單純的數據庫開發【膚淺…

部署Flink1.20.1

1、設置環境變量 export JAVA_HOME/cluster/jdk export CLASSPATH.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jarp #export HIVE_HOME/cluster/hive export MYSQL_HOME/cluster/mysql export HADOOP_HOME/cluster/hadoop3 export HADOOP_CONF_DIR$HADOOP_HOME/etc/hadoop …

【超詳細】神經網絡的可視化解釋

《------往期經典推薦------》 一、AI應用軟件開發實戰專欄【鏈接】 項目名稱項目名稱1.【人臉識別與管理系統開發】2.【車牌識別與自動收費管理系統開發】3.【手勢識別系統開發】4.【人臉面部活體檢測系統開發】5.【圖片風格快速遷移軟件開發】6.【人臉表表情識別系統】7.【…