天天看點

PostgreSQL 11 新特性解讀: 增加對JIT(just-in-time)編譯的支援提升分析型SQL執行效率關于 JITJIT 使用場景手冊 Release說明安裝環境LLVM安裝前提條件安裝 Cmake 3.12.3安裝Python 2.7.9安裝 LLVM 5.0.2PostgreSQL 11 安裝JIT 測試參考新書推薦

關于 JIT

PostgreSQL 11 版本的一個重量級新特性是引入了

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 all        all     0.0.0.0/0       md5           

之後啟動資料庫,如下:

[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% 左右。

參考

新書推薦

最後推薦和張文升共同編寫的《PostgreSQL實戰》,本書基于PostgreSQL 10 編寫,共18章,重點介紹SQL進階特性、并行查詢、分區表、實體複制、邏輯複制、備份恢複、高可用、性能優化、PostGIS等,涵蓋大量實戰用例!

購買連結:

https://item.jd.com/12405774.html
PostgreSQL 11 新特性解讀: 增加對JIT(just-in-time)編譯的支援提升分析型SQL執行效率關于 JITJIT 使用場景手冊 Release說明安裝環境LLVM安裝前提條件安裝 Cmake 3.12.3安裝Python 2.7.9安裝 LLVM 5.0.2PostgreSQL 11 安裝JIT 測試參考新書推薦