PostgreSQL 11 新特性解讀: 增加對JIT(just-in-time)編譯的支援提升分析型SQL執行效率
關於 JIT
PostgreSQL 11 版本的一個重量級新特性是引入了 ofollow,noindex" target="_blank"> JIT (Just-in-Time) 編譯來加速SQL中的表示式計算效率。
JIT 表示式的編譯使用LLVM專案編譯器的架構來提升在WHERE條件、指定列表、聚合以及一些內部操作表示式的編譯執行。
使用 JIT 必須在首先編譯安裝 LLVM ,之後編譯安裝 PostgreSQL 時設定 --with-llvm
選項,本文主要包括兩部分,如下:
- CentOS7 編譯安裝 LLVM。
- CentOS7 編譯安裝PostgreSQL 11,啟用並演示 JIT。
JIT 使用場景
JIT 常用於CPU密集型SQL(分析統計SQL),執行很快的SQL使用JIT由於產生一定開銷,反而可能引起效能下降。
手冊 Release說明
Add Just-in-Time (JIT) compilation of some parts of query plans to improve execution speed (Andres Freund)
This feature requires LLVM to be available. It is not currently enabled by default, even in builds that support it.
安裝環境
作業系統: CentOS Linux release 7.4.1708 (Core)
硬體環境: 8核4G/80G 的雲主機
LLVM安裝前提條件
LLVM 安裝依賴較多,如下:
The minimum required version of LLVM is currently 3.9--本實驗使用 LLVM 5.0.2 CMake. Version 3.4.3 is the minimum required.--本實驗使用 Cmake 3.12.3 Python 2.7 or newer is required--本實驗使用 Python 2.7.9 GCC version must be at least 4.8!--本實驗使用 gcc 4.8.5
安裝 Cmake 3.12.3
下載並編譯安裝 cmake 3.12.3,如下:
# wget -c https://cmake.org/files/v3.12/cmake-3.12.3.tar.gz # tar xvf cmake-3.12.3.tar.gz # cd cmake-3.12.3 # ./bootstrap # make -j 4 # make install
安裝Python 2.7.9
下載並編譯安裝 python 2.7.9,如下:
# wget -c https://www.python.org/downloads/release/python-279/ # tar jxvf Python-2.7.9.tgz # cd Python-2.7.9 # ./configure # make # make install
安裝 LLVM 5.0.2
LLVM 的安裝步驟較繁瑣,並且編譯安裝過程時間較長,效能好的機器能減少編譯時間,注意作業系統需啟用 swap
,否則編譯過程中會報錯,本人開始編譯安裝時沒有啟用 swap
,折騰了很久。
下載LLVM安裝介質
在 LLVM官網 下載安裝介質,如下:
llvm-5.0.2.src.tar.xz cfe-5.0.2.src.tar.xz clang-tools-extra-5.0.2.src.tar.xz compiler-rt-5.0.2.src.tar.xz libcxx-5.0.2.src.tar.xz libcxxabi-5.0.2.src.tar.xz libunwind-5.0.2.src.tar.xz
編譯安裝LLVM
解壓 llvm-5.0.2.src.tar.xz
# cd /opt/soft_bak/ # tar xvf llvm-5.0.2.src.tar.xz # mv llvm-5.0.2.src llvm
解壓安裝包並重命名,目錄結構對應如下,如下:
安裝包 | 安裝目錄 |
---|---|
llvm-5.0.2.src.tar.xz | /opt/soft_bak/llvm |
cfe-5.0.2.src.tar.xz | /opt/soft_bak/tools/clang |
clang-tools-extra-5.0.2.src.tar.xz | /opt/soft_bak/tools/clang/tools/extra |
compiler-rt-5.0.2.src.tar.xz | /opt/soft_bak/projects/compiler-rt |
libcxx-5.0.2.src.tar.xz | /opt/soft_bak/projects/libcxx |
libcxxabi-5.0.2.src.tar.xz | /opt/soft_bak/projects/libcxxabi |
libunwind-5.0.2.src.tar.xz | /opt/soft_bak/projects/libunwind |
LLVM 官網的其它安裝包非必須,可根據情況選擇。
編譯安裝 LLVM,如下:
# mkdir -p /opt/soft_bak/llvm_build/ # cd /opt/soft_bak/llvm_build/ # cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=/usr/local/llvm -DCLANG_DEFAULT_CXX_STDLIB=libc++ -DCMAKE_BUILD_TYPE="Release" /opt/soft_bak/llvm # make -j 4 # make install
設定環境變數,如下:
export PATH=$PATH:/usr/local/llvm/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/llvm/lib
檢視版本
[root@pghost7 ~]# llvm-cat --version LLVM (http://llvm.org/): LLVM version 5.0.2 Optimized build. Default target: x86_64-unknown-linux-gnu Host CPU: broadwell [root@pghost7 ~]# clang --version clang version 5.0.2 (tags/RELEASE_502/final) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/local/llvm/bin
至此 LLVM 已安裝成功。
PostgreSQL 11 安裝
安裝相關包,如下:
# yum -y install gcc readline readline-devel zlib zlib-devel python-devel
下載PostgreSQL 11 並編譯安裝,編譯時指定 --with-llvm
選項, 如下:
# wget -c https://ftp.postgresql.org/pub/source/v11.0/postgresql-11.0.tar.bz2 # tar xvf postgresql-11.0.tar.bz2 #./configure --prefix=/opt/pgsql_11.0 --with-wal-blocksize=16 -with-pgport=1930 --with-llvm LLVM_CONFIG='/usr/local/llvm/bin/llvm-config' # make wolrd -j 4 # make install-world
設定 .bash_profile
,如下:
export PGPORT=1930 export PGUSER=postgres export PGDATA=/database/pg11/pg_root export LANG=en_US.utf8 export PGHOME=/opt/pgsql_11.0 export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib export DATE=`date +"%Y%m%d%H%M"` export PATH=$PGHOME/bin:$PATH:. export MANPATH=$PGHOME/share/man:$MANPATH alias rm='rm -i' alias ll='ls -lh'
使用 initdb
初始化資料庫,如下:
[pg11@pghost7 pg_root]$ initdb -D /database/pg11/pg_root -E=UTF8 --locale=C -U postgres -W
postgresql.conf 設定以下 JIT 配置引數,其它引數按需配置,這裡不貼出,如下:
# - Other Defaults - #dynamic_library_path = '$libdir' jit = on# allow JIT compilation jit_provider = 'llvmjit'# JIT implementation to use
設定 pg_hba.conf,如下:
host allall0.0.0.0/0md5
之後啟動資料庫,如下:
[pg11@pghost7 pg_root]$ pg_ctl start waiting for server to start....2018-10-31 11:13:26.154 CST [19742] LOG:listening on IPv4 address "0.0.0.0", port 1930 2018-10-31 11:13:26.154 CST [19742] LOG:listening on IPv6 address "::", port 1930 2018-10-31 11:13:26.159 CST [19742] LOG:listening on Unix socket "/tmp/.s.PGSQL.1930" 2018-10-31 11:13:26.185 CST [19742] LOG:redirecting log output to logging collector process 2018-10-31 11:13:26.185 CST [19742] HINT:Future log output will appear in directory "log". done server started
JIT 測試
以下大致演示 JIT,測試樣例很簡單,不做充分的效能測試,有興趣的朋友可以做 TPC-H 效能測試。
測試資料準備
建立一張5千萬的資料表,如下:
CREATE TABLE t_llvm1(a int4, b int4, info text, ctime timestamp(6) without time zone); INSERT INTO t_llvm1 (a,b,info,ctime) SELECT n,n*2,n||'_llvm1',clock_timestamp() FROM generate_series(1,50000000) n;
檢視 JIT 相關引數
postgres=# SELECT name,setting FROM pg_settings WHERE name LIKE 'jit%'; name| setting -------------------------+--------- jit| on jit_above_cost| 100000 jit_debugging_support| off jit_dump_bitcode| off jit_expressions| on jit_inline_above_cost| 500000 jit_optimize_above_cost | 500000 jit_profiling_support| off jit_provider| llvmjit jit_tuple_deforming| on (10 rows)
開啟 JIT
開啟 JIT,執行計劃如下:
postgres=# SET JIT = on; SET postgres=# EXPLAIN ANALYZE SELECT count(*),sum(a) FROM t_llvm1 WHERE (a+b) > 10; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------- Finalize Aggregate(cost=576982.30..576982.31 rows=1 width=16) (actual time=2148.607..2148.608 rows=1 loops=1) ->Gather(cost=576981.86..576982.28 rows=4 width=16) (actual time=2148.457..2153.185 rows=5 loops=1) Workers Planned: 4 Workers Launched: 4 ->Partial Aggregate(cost=575981.86..575981.88 rows=1 width=16) (actual time=2134.919..2134.919 rows=1 loops=5) ->Parallel Seq Scan on t_llvm1(cost=0.00..555148.48 rows=4166677 width=4) (actual time=105.597..1516.253 rows=9999999 loops=5) Filter: ((a + b) > 10) Rows Removed by Filter: 1 Planning Time: 0.078 ms JIT: Functions: 28 Options: Inlining true, Optimization true, Expressions true, Deforming true Timing: Generation 5.842 ms, Inlining 226.589 ms, Optimization 191.071 ms, Emission 107.027 ms, Total 530.529 ms Execution Time: 2154.870 ms (14 rows)
從以上看出執行計劃中包含 JIT 編譯資訊,執行時間為 2154 ms 左右。
關閉 JIT
關閉 JIT,檢視執行計劃和掃行時間,如下:
postgres=# SET JIT = off; SET postgres=# EXPLAIN ANALYZE SELECT count(*),sum(a) FROM t_llvm1 WHERE (a+b) > 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------ Finalize Aggregate(cost=576982.30..576982.31 rows=1 width=16) (actual time=2382.035..2382.035 rows=1 loops=1) ->Gather(cost=576981.86..576982.28 rows=4 width=16) (actual time=2381.939..2385.143 rows=5 loops=1) Workers Planned: 4 Workers Launched: 4 ->Partial Aggregate(cost=575981.86..575981.88 rows=1 width=16) (actual time=2371.143..2371.143 rows=1 loops=5) ->Parallel Seq Scan on t_llvm1(cost=0.00..555148.48 rows=4166677 width=4) (actual time=0.560..1600.125 rows=9999999 loops=5) Filter: ((a + b) > 10) Rows Removed by Filter: 1 Planning Time: 0.083 ms Execution Time: 2385.209 ms (10 rows)
從以上看出執行計劃中沒有包含 JIT 資訊,執行時間為 2385 ms 左右,開啟JIT效能提升了9.7% 左右。
參考
- Chapter 32. Just-in-Time Compilation (JIT)
- The LLVM Compiler Infrastructure
- PostgreSQL 已包含對 LLVM JIT 支援的提交效能將飆升
- How to compile PostgreSQL 11 with support for JIT compilation on RHEL/CentOS 7
- PostgreSQL 11 and Just In Time Compilation of Queries
- Speeding up query execution in PostgreSQL using LLVM JIT compiler
- PostgreSQL 11.0 正式版更新版本釋出說明
新書推薦
最後推薦和張文升共同編寫的《PostgreSQL實戰》,本書基於PostgreSQL 10 編寫,共18章,重點介紹SQL高階特性、並行查詢、分割槽表、物理複製、邏輯複製、備份恢復、高可用、效能優化、PostGIS等,涵蓋大量實戰用例!
購買連結: https://item.jd.com/12405774.html