LLVM技術在GaussDB等資料庫中的應用

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

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


本文分享自華為雲社區《【GaussTech第3期】LLVM技術在GaussDB等資料庫中的應用》,作者:GaussDB 資料庫。

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根據實際情況消除了不必要的迴圈和判斷。

11.png

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

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

22.png

▲ 圖2 LLVM的實現粒度

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

33.png

▲ 圖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)的情況下,和簡單的查詢相比,Plancache + CodeGen將TPS從21.8提升到了43,性能上有了約兩倍的提升。

44.png

▲ 圖4 簡單查詢、CodeGen流程、Plancache和“Plancache +CodeGen”流程的性能對比

GaussDB中的LLVM

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

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

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

55.png

▲ 圖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技術進行性能優化。

20240527-163414(WeLinkPC).png

▲ 圖6 GaussDB LLVM 模塊層次圖

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

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

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

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

77.png

▲ 圖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的表達式:

11111.PNG

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

在向量化執行引擎中,僅當表達式出現在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性能測試。

111.PNG

▲ 表1 測試環境

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

222.PNG

▲ 表2 TPCH 部分Query的測試結果

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

PostgreSQL中的LLVM

1. LLVM在PostgreSQL應用的時間線

LLVM在PostgreSQL社區中的技術討論開始的比較早:

2015年,上文提到的華為在PostgreSQL開發者大會上做的演講;

2016年,PostgreSQL社區開始對JIT的實現進行了討論;

2018年,PostgreSQL11中,第一次正式採用LLVM加速表達式計算。

2. PostgreSQL LLVM實現簡析

如下圖所示,和GaussDB相同,PostgreSQL執行引擎使用CodeGen技術做性能優化。針對錶達式求值和元組分解為所需的屬性集合兩大性能瓶頸,做了可選的編譯執行加速。

88.png

▲ 圖 8 PgSQL LLVM 模塊層次圖

PostgreSQL使用了三個參數來判斷是否使用CodeGen優化:

  • jit_above_cost,表示超過多少cost 的查詢才會使用JIT 功能。預設為100000,如果設置為-1 則關閉JIT。
  • jit_inline_above_cost,表示超過多少cost 的查詢使用JIT 的inline 功能。預設為500000,-1則關閉inline 功能。
  • jit_optimize_above_cost,表示超過多少cost 的查詢使用JIT 的optimization 功能。預設為500000,-1則關閉優化功能。

其中,後兩個參數都需要設置得比jit_above_cost大,否則沒有意義。這和GaussDB的使用數據集大小來控制是否開啟CodeGen思想類似。

另外,PostgreSQL對於LLVM生成的位元組碼目前無法在plan cache中復用。這個功能的實現在PostgreSQL的中長期計劃中。

3. PostgreSQL LLVM支持加速的場景

當前,PostgreSQL的JIT實現支持對錶達式計算以及元組拆解的加速。

表達式計算被用來計算WHERE子句、target lists, aggregate聚合和projections投影。通過為每一種情況生成專門的代碼來實現加速。

元組拆解是把一個磁碟上的元組轉換成其在記憶體中表示的過程。通過創建一個專門針對該表佈局和要被抽取的列數的函數來實現加速。

總結

華為和PostgreSQL關於LLVM特性的研究都起步很早,華為作為LLVM技術應用於資料庫先驅者引領了PostgreSQL的技術發展。對於LLVM應用於資料庫,GaussDB和PostgreSQL各有實現方法。GaussDB作為企業級資料庫,對比PostgreSQL資料庫,其實現特性多於PostgreSQL。

999.PNG

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

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

如何參與?

長按識別二維碼,即可參與!

有碼海報.jpg

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

 


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

-Advertisement-
Play Games
更多相關文章
  • 環境準備 利用 OpenSSL 簽發證書需要 OpenSSL 軟體及庫,一般情況下 CentOS、Ubuntu 等系統均已內置, 可執行 openssl 確認,如果提示 oepnssl: command not found,則需手動安裝,以Centos為例: yum install openssl ...
  • 介紹 HMI-Board為 RT-Thread 聯合瑞薩推出的高性價比圖形評估套件,取代傳統的 HMI+主控板硬體,一套硬體即可實現 HMI+IoT+控制的全套能力。依托於瑞薩高性能晶元 RA6M3 及 RT-Thread 軟體生態,HMI-Board 不僅硬體性能強勁,同時軟體生態豐富,助力開發者 ...
  • 系統編程 POSIX信號量 題目 設計一個程式,主線程需要創建2個子線程之後主線程終止,此時進程中有2個子線程A和B,此時進程中有一個臨界資源flag,子線程A獲取觸摸屏坐標並判斷坐標值是否在LCD屏的左上角,如果坐標範圍滿足左上角,則利用條件量和互斥鎖來喚醒子線程B,子線程B的任務是判斷flag ...
  • 目錄題目解析代碼結果展示 題目 解析 ​ 該題主要依靠條件量和互斥鎖來實現線程之間的同步與互斥,分析主線程、線程A和線程B的任務如下: 主線程: 打開LCD屏和觸摸屏的硬體文件,並分別存儲兩個文件的文件描述符,方便後面進行條件判斷。 開啟線程A和線程B。 定義並初始化條件量和互斥量,方便後續線程內進 ...
  • 任務的掛起與恢復的API函數介紹 API函數 描述 vTaskSuspend() 掛起任務 vTaskResume() 恢復被掛起的任務 xTaskResumeFromISR() 在中斷中恢復被掛起的任務 1、掛起任務類似暫停,可恢復; 刪除任務,無法恢復 2、恢復是恢復被掛起任務 3、帶FromI ...
  • VXLAN在雲網路中應用十分廣泛。本文介紹一種方法在兩台Linux主機之間建立簡單的VXLAN隧道,以供學習、研究之用。 ...
  • 很多APP都需要主動向用戶推送消息,這就需要用到長連接的服務,即我們通常提到的websocket,同樣也是使用socket服務,通信協議是基本類似的,在go中用的最多的、也是最簡單的socket服務就是gorilla/websocket,它有21.1K的star,足以說明它的受歡迎程度, 它的git ...
  • 本文測試環境為SQLserver2019 背景 某業務流水錶,會基於固定範圍內的業務編號做寫入以及查詢操作,熱數據的量級在億級別,一個典型的查詢是基於業務編碼查詢最新(時間戳)某種狀態的前N條數據 簡化後的表結構如下 create table TestTable01 ( id bigint iden ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...