深度解讀資料庫引入LLVM技術後如何提升性能

来源:https://www.cnblogs.com/huaweiyun/p/18243298
-Advertisement-
Play Games

GaussDB作為企業級的資料庫,經過了多年的技術發展,具備豐富的技術特性,使用LLVM技術後提升了系統的查詢性能,使得開發者在OLAP和OLTP多場景中均受益。 ...


GaussDB作為企業級的資料庫,經過了多年的技術發展,具備豐富的技術特性,使用LLVM技術後提升了系統的查詢性能,使得開發者在OLAP和OLTP多場景中均受益。

Hi,別急!讓技術觸達每一個角落,賦能更多的人,GaussTech第3期《LLVM技術在GaussDB等資料庫中的應用》,不僅帶來滿滿的技術乾貨,還推出【分享集贊回帖贏好禮】活動,參與就能贏好禮,點擊鏈接參與!

萬物互聯的態勢下,數據量的激增使得“如何提升數據處理性能”成為各家資料庫共同面臨的挑戰。作為編譯優化技術的代表,基於LLVM的CodeGen技術,能為每個查詢生成定製的機器碼替代原本的通用函數,減少實際查詢時冗餘的條件邏輯判斷、虛函數調用並提高數據局域性,從而達到提升查詢整體性能的目的,成為資料庫性能優化的一項重要技術。

LLVM能在分析類場景中給用戶帶來較大的收益,也能在特定的交易性場景中給用戶帶來一定的收益。接下來詳細解讀一下LLVM技術在GaussDB中的應用吧。

LLVM和資料庫

LLVM(Low Level Virtual Machine)是一款流行的開源編譯器框架,是CodeGen(生成源代碼的工具)技術的事實標準,被廣泛運用於資料庫(如KES,AnalyticDB,GaussDB)、大數據(如Spark)、AI平臺(如tensorflow)等領域,用於提升數據處理的性能。

在沒有引入LLVM這類CodeGen技術之前,資料庫會使用通用的處理邏輯來處理數據,但通用邏輯“笨重”(遞歸、封裝、類型判斷轉換)的代碼實現方式,存在虛函數開銷、緩存使用率低下、對指令集不敏感等性能短板。

引入LLVM之後,可以為具體的查詢生成定製化的機器碼,並儘可能的將數據存儲在CPU的寄存器中進一步加快計算的速度:

  • LLVM天然支持JIT,該技術可以解決條件邏輯冗餘的問題;
  • 減少大量的虛函數調用;
  • 將數據儘可能的從記憶體載入到Cache上;
  • LLVM做了很多自動矢量化的工作;

比如,下圖左側是通用代碼,右側是CodeGen之後的代碼。CodeGen根據實際情況消除了不必要的迴圈和判斷。

圖1 通用性處理邏輯和LLVM代碼示意

另外,LLVM技術可以有不同的實現粒度。比如:可使用LLVM加速表達式計算,或再進一步,將多個運算元融合編譯成定製的機器碼,或將自定義函數、存儲過程等編譯成定製的機器碼。

圖2 LLVM的實現粒度

資料庫在執行引擎中,運用LLVM技術提升SQL的執行速度。如下圖所示:

圖3 LLVM技術運用於執行引擎

LLVM適用場景

LLVM對所有類型的SQL都會有收益嗎?

答案是否定的。

因為執行實時編譯本身需要耗費一定的時間(簡單表達式能做到毫秒級,複雜情況在百毫秒級),對於查詢本身耗時較少的場景,加入LLVM反而會導致性能劣化。

因此,目前LLVM在OLAP/HTAP分析型業務場景中收益較大,有著廣泛應用,而在OLTP交易型業務場景中,則相對沒有那麼廣泛。

LLVM在OLTP中就一定沒有收益嗎?

答案同樣是否定的。

找對場景,一樣有收益。比如根據ISPRAS 2017年發表的實驗結果  jit-compiling sql queries in postgresql using llvm可知:pgbench測試下,OLTP場景中簡單的查詢加上JIT(Just-in-time及時編譯,LLVM天然支持)擴展沒有帶來性能的提升,甚至將TPS(事務數/秒)從21.8降低到了7.8。

但是在Prepared query(plan cached)的情況下,疊加 JIT技術之後將TPS從20.7提升到了43,性能上有了兩倍的提升。

GaussDB中的LLVM

1. LLVM在華為應用於資料庫的時間線

華為雲資料庫在LLVM上的研究還是非常超前的。早在2015年,華為就作為某流行開源資料庫社區的全球開發者大會的贊助商,在會上發表的動態編譯(Go Faster with Native Compilation)演講,引起了很大的反響。

當時社區領袖Josh Burkus在其博客裡面,用一節篇幅專門詳細介紹了華為動態編譯的議題。

圖5 2015年社區領袖Josh Burkus介紹華為的動態編譯議題

在2017年,華為在面向OLAP場景的資料庫內核中突破了LLVM動態編譯技術,併在多個運營商、金融證券的POC項目中幫助客戶提升數據處理性能,同時,在軟體開發過程中充分模塊化、通用化介面設計,將LLVM同年落地到面向OLTP的資料庫設計中。

目前,GaussDB資料庫對於LLVM也在不斷的演進開發。

2. GaussDB LLVM實現簡析

GaussDB針對向量化引擎(主要用於分析場景)、行存(主要用於交易場景)都實現了CodeGen。如下圖所示,從代碼模塊層次來看:

1) GaussDB通過API介面層封裝處理了LLVM環境、資源、基本元素等。

2) GaussDB在CodeGen層調用API介面進行了不同粒度的實現。

3) GaussDB在執行引擎側根據情況使用CodeGen技術進行性能優化。

圖6 GaussDB LLVM 模塊層次圖

GaussDB啟動後會進行LLVM的初始化工作,檢查CPU對CodeGen的支持情況,併進行環境初始化。

在執行啟動階段,以表達式為例,程式會判斷當前表達式是否可JIT,是的話,則會進行IR函數的生成和生成定製機器碼,及原本表達式執行函數的入口替代工作。

在實際執行過程中,運行處理函數(該函數已經在上一階段進行了入口替代)進行實際執行工作。

在執行結束後的清理階段,釋放LLVM相關資源。

圖7 GaussDB CodeGen編譯執行流程簡圖

GaussDB使用了閾值codegen_cost_threshold來估算當前查詢使用LLVM技術是否能帶來收益。如果處理數據的規模大於該閾值後,才會繼續使用LLVM技術進行相關處理。該閾值代表行數,也可以理解成處理數據的規模,預設值為100000行,可以調節。

在OLAP場景中,GaussDB在判斷是否能夠對於一個運算元進行CodeGen後(如:數據類型,運算元類型判斷等),開始生成對應的IR bytecode片段,之後MCJIT模塊會調用生成的LLVM Module單元進行執行。

在OLTP場景中,GaussDB則會在Plan Cache場景下結合CodeGen框架,通過緩存機器碼的方式,節省下編譯生成中間語言IR Func以及優化成機器碼的時間,整個過程是非同步的。因此,在大量重覆查詢的場景下,後續的查詢也會因為LLVM技術而受益。

另外,為了避免行數估計錯誤而選擇CodeGen導致性能劣化,GaussDB還研發了當前業界獨有的非同步編譯功能,即在查詢語句確定要使用CodeGen的時候,將編譯工作轉交給後臺線程,工作線程在JIT函數編譯完成前繼續使用原始執行邏輯執行,編譯完成後,再替換成JIT函數執行。

3. GaussDB LLVM支持加速的場景

支持LLVM的表達式:

行存表達式計算支持的數據類型不受限制。

在向量化執行引擎中,僅當表達式出現在Scan節點的filter、Hash Join節點中的complicate hash condition,hash join filter,hash join target, Nested Loop節點中的filter,join filter, Merge Join節點的merge join filter, merge join target, Group節點中的filter表達式時,才會考慮是否使用LLVM動態編譯優化。

在行存執行引擎中,除一次性的表達式計算外,會考慮為所有運算元的filter和Targetlist表達式都使用LLVM動態編譯優化。

支持LLVM的運算元:

Join :HashJoin(僅向量化執行引擎支持)

Agg :HashAgg

Sort(僅向量化執行引擎支持)

其中,HashJoin運算元僅支持Hash Inner Join,對應的hash cond僅支持int4、bigint、bpchar類型的比較;HashAgg運算元僅支持針對bigint、numeric類型的sum及avg操作,且group by語句僅支持int4、bigint、bpchar,text,varchar,timestamp類型操作,同時支持count(*)聚集操作。Sort運算元僅支持對int4,bigint,numeric,bpchar,text,varchar數據類型的比較操作。除此之外,無法使用LLVM動態編譯優化,具體可通過explain performance工具進行顯示。

4. GaussDB LLVM使用建議

GUC參數:

enable_codegen:控制LLVM特性的打開和關閉。目前資料庫內核側預設打開。

codegen_cost_threshold:使用處理行數控制是否開啟codegen,預設為10000。10000是通過實驗驗證得出的優化值,不建議將此值設置的過低。

另外,在開啟LLVM特性的前提下,建議在允許的條件下儘可能設置較大的work_mem,如果出現大量下盤,則建議關閉LLVM動態編譯優化。用戶可通過analysis_options為on(LLVM_COMPILE),執行對應查詢語句,在User Define Profiling中就可以看到LLVM的編譯時間。結合此數據,可對codegen_cost_threshold進一步調整以獲取更好的查詢性能。

5. GaussDB LLVM性能表現

GaussDB實驗室分別就codegen打開和關閉進行了TPCH性能測試。

操作系統

EulerOS release 2.0 (SP8)

CPU

128核 * aarch64

記憶體

2.0Ti

表1 測試環境

測試結果顯示,打開codegen時,帶有qual的SQL,查詢性能都有明顯提升,且提升比例與qual在整個SQL中的占比相關,像Q6、Q12、Q19等qual占比較高的查詢,性能提升也較多。

TPCH

數據量

qual(Expr)

測試結果
(s)

性能提升

Q6

0.9億

l_shipdate >= '1994-01-01'::date
and l_shipdate < '1994-01-01'::date + interval '1 year'
and l_discount between 0.06 - 0.01 and 0.06 + 0.01
and l_quantity < 24;

66

52

21%

Q12

6.0億

and l_shipmode in ('MAIL', 'SHIP')
and l_commitdate < l_receiptdate
and l_shipdate < l_commitdate
and l_receiptdate >= date '1994-01-01'
and l_receiptdate < date '1994-01-01' + interval '1 year'

306

210

31%

Q19

6.0億

and l_shipmode in ('AIR', 'AIR REG')
and l_shipinstruct = 'DELIVER IN PERSON'

296

208

30%

表2 TPCH 部分Query的測試結果

TPCC的性能提升並沒有TPCH那麼多,但據實驗室數據,打開codegen後,tpmC提升了約7%。

總結

LLVM被廣泛運用於資料庫、大數據、AI等領域。在資料庫領域,多家商業資料庫和開源資料庫都應用其加速資料庫處理。GaussDB作為企業級的資料庫,經過了多年的技術發展,具備豐富的技術特性,使用該技術後提升了系統的查詢性能,使得客戶在OLAP和OLTP多場景中均受益。

“【分享集贊回帖贏好禮】LLVM技術在GaussDB等資料庫中的應用”活動來啦!參與就有機會贏取華為背包、華為雲定製短袖、藍牙音箱、書籍等好禮!

活動時間:2024/5/28-6/17

如何參與?

點擊鏈接:https://bbs.huaweicloud.com/forum/thread-0249152272038530018-1-1.html

cke_3080.png

HDC 2024,6月21日-23日,東莞松山湖,期待與您相見!

更多詳情請關註官網:

中文:https://developer.huawei.com/home/hdc

英文:https://developer.huawei.com/home/en/hdc

點擊關註,第一時間瞭解華為雲新鮮技術~

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 問題 有很多應用程式在驗證JSON數據的時候用到了JSON Schema。 在微服務架構下,有時候各個微服務由於各種歷史原因,它們所生成的數據對JSON Object屬性名的大小寫規則可能並不統一,它們需要消費的JSON數據的屬性名可能需要大小寫無關。 遺憾的是,目前的JSON Schema沒有這方 ...
  • 首先下載centos07鏡像,建議使用阿裡雲推薦的地址: https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spm=a2c6h.25603864.0.0.59b5f5ad5Nfr0X 其實這裡就已經出現第一個坑了 centos 07 /u ...
  • 相信很多.NETer看了標題,都會忍不住好奇,點進來看看,並且順便準備要噴作者! 這裡,首先要申明一下,作者本人也非常喜歡Linq,也在各個項目中常用Linq。 我愛Linq,Linq優雅萬歲!!!(PS:順便吐槽一下,隔壁Java從8.0版本推出的Streams API,抄了個四不像,一點都不優雅 ...
  • 在人生的重要時刻,我站在了畢業的門檻上,望著前方的道路,心中涌動著對未來的無限憧憬與些許忐忑。面前,兩條道路蜿蜒伸展:一是繼續在職場中尋求穩定,一是勇敢地走出一條屬於自己的創新之路。儘管面臨年齡和現實的挑戰,我仍舊選擇勇往直前,用技術這把鑰匙,開啟新的人生篇章。 迴首過去,我深知時間寶貴,精力有限。 ...
  • 單元測試 前言 時隔多個月,終於抽空學習了點新知識,那麼這次來記錄一下C#怎麼進行單元測試,單元測試是做什麼的。 我相信大部分剛畢業的都很疑惑單元測試是乾什麼的?在小廠實習了6個月後,我發現每天除了寫CRUD就是寫CRUD,幾乎用不到單元測試。寫完一個功能直接上手去測,當然這隻是我個人感受,僅供參考 ...
  • 一:背景 1. 講故事 最近在分析dump時,發現有程式的卡死和WeakReference有關,在以前只知道怎麼用,但不清楚底層邏輯走向是什麼樣的,藉著這個dump的契機來簡單研究下。 二:弱引用的玩法 1. 一些基礎概念 用過WeakReference的朋友都知道這裡面又可以分為弱短和弱長兩個概念 ...
  • 最近想把ET打表工具的報錯提示直接調用win系統彈窗,好讓策劃明顯的知道表格哪裡填錯數據,彈窗需要調用System.Windows.Forms庫。操作如下: 需要在 .csproj 文件中添加: <UseWindowsForms>true</UseWindowsForms> 須將目標平臺設置為 Wi ...
  • 從C#3開始,拓展方法這一特性就得到了廣泛的應用。 此功能允許你能夠使用實例方法的語法調用某個靜態方法,以下是一個獲取/創建文件的靜態方法: public static async Task<StorageFile> GetOrCreateFileAsync(this StorageFolder f ...
  • 在Windows 11下,使用WinUI2.6以上版本的ListView長這樣: 然而到了Win10上,儘管其他控制項的樣式沒有改變,但ListViewItem變成了預設樣式(初代Fluent) 最重大的問題是,Win10上的HorizontalAlignment未被設置成Stretch,可能造成嚴重 ...
  • 前言 周六在公司加班,幹完活後越顯無聊,想著下載RabbiitMQ做個小項目玩玩。然而這一下就下載了2個小時,真讓人頭痛。 簡單的講一下如何安裝吧,網上教程和踩坑文章還是很多的,我講我感覺有用的文章放在本文末尾。 安裝地址 erlang 下載 - Erlang/OTP https://www.erl ...