我試用了PostgreSQL 11的新功能JIT編譯

首先

2018年10月18日,PostgreSQL 11发布了。

    • PostgreSQL 11 Released

 

    https://www.postgresql.org/about/news/1894/

大规模数据库的各种功能得到了加强,比如并行查询和分区等等。今天我要分享的是其中一个我个人特别关注的、并且构建起来比较困难的JIT编译功能的验证内容。

在撰写本文时,我参考了各种信息,并附上了相应的链接。
然而,部分链接是关于PostgreSQL 11测试版的验证信息。
请注意,和正式发布的PostgreSQL 11可能存在不同的结果。

引入JIT编译

即使正常安装了PostgreSQL 11,也不一定可以使用JIT编译。
默认情况下,需要安装未安装的库等。

如果从源代码构建PostgreSQL

如果要从源代码搭建PostgreSQL,需要先安装LLVM。 (CentOS 7等默认安装了LLVM,但版本较旧,需要进行调整)

在编译时,需要明确使用LLVM作为选项。

从源代码构建并引入LLVM的步骤在详细的建立和验证网站上有说明。然而,以下信息是关于PostgreSQL 11测试版的信息。请注意,目前可能存在升级所需LLVM版本的情况。

如果从RPM安装PostgreSQL的话

以前我写过一篇文章(推广)关于使用RPM安装PostgreSQL。
请参考这篇文章获取详细的安装步骤。
适用于初学者和注重细节的用户从RPM安装PostgreSQL。

在线环境下

通过上述文章介绍的从RPM安装PostgreSQL,可以使用JIT支持的构建。但是由于操作系统上的LLVM版本可能无法正确配合,所以需要注意。

有关LLVM版本升级的方法,请参考本网站提供的建设和验证相关内容的链接。

在离线环境下

LLVM可以从EPEL(Linux扩展包)获取。
这次我们将获取5.0或以上的版本。

    • EPEL/ja

 

    https://fedoraproject.org/wiki/EPEL/ja

在离线环境下,可以直接从上述的网站获取所需的RPM,并将其安装在目标环境中。

在CentOS 7上,
从https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/l/
下载”llvm5.0-libs-5.0.1-7.el7.x86_64.rpm”和”llvm5.0-5.0.1-7.el7.x86_64.rpm”。

yum install llvm5.0-libs-5.0.1-7.el7.x86_64.rpm
yum install llvm5.0-5.0.1-7.el7.x86_64.rpm

从以下网站选择适当的操作系统行和版本号,您可以找到所有与PostgreSQL相关的RPM包。然后获取LLVM相关的RPM。

    • PostgreSQL RPM Chart

 

    https://yum.postgresql.org/rpmchart.php

在CentOS 7环境中,下载PostgreSQL 11的文件「postgresql11-llvmjit-11.0-1PGDG.rhel7.x86_64.rpm」,链接为https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7.4-x86_64/。

yum install postgresql11-llvmjit-11.0-1PGDG.rhel7.x86_64.rpm

这样一来,就成为了能够使用JIT编译的环境。

让我们实际尝试使用一下

即使JIT编译可以使用,也并非立即可用。
需要调整相关参数。

关于参数问题,我们有手册和PostgreSQL 11来帮忙!(1)- 参考了参数差异的文章。
除了JIT相关内容外,由于PostgreSQL 11增加/修改了参数的说明,对于PostgreSQL相关人员来说是必看的。
另外,正如(1)中所述,作者ぬこ@横浜先生撰写了许多关于11版本的文章。
我个人在PostgreSQL 11验证中也参考了这些文章,所以强烈推荐(代传)。

JIT相关的参数

以下是使用JIT编译所需的参数集。
其中jit_above_cost、jit_inline_above_cost和jit_optimize_above_cost这三个参数具有较强的关联性。
您可以通过修改这些参数来正确使用JIT编译。

パラメータ名デフォルト値説明jitoffJITコンパイルの使用可能にするかを決めます。
ベータ版ではデフォルトでonでしたが、正式版ではoffがデフォルトです。jit_above_cost100000JITコンパイルが使用されるかを決めるコストの閾値です。
クエリの推定コストが本値を超えると使用されます。
値が-1の場合、無効化されます。jit_inline_above_cost500000JITコンパイル使用後に、インライン展開するかを決める閾値です。
JITコンパイルのオーバヘッドは増加しますが、クエリ実行時間は減ります。
クエリの推定コストが本値を超えると使用されます。
値が-1の場合、無効化されます。jit_optimize_above_cost500000インライン展開後、高価な最適化をするか決める閾値です。
JITコンパイルのオーバヘッドは増加しますが、クエリ実行時間は減ります。
クエリの推定コストが本値を超えると使用されます。
値が-1の場合、無効化されます。jit_providerllvmjit使用するJITプロパイダを決定します。
現在はLLVMのみ対応しているため変更の必要はありません。

除了这个之外,还有一些供开发者使用的参数,但我认为在正常运营时不需要特别关注。

尝试更改参数并使用JIT编译

只要降低JIT编译的可用阈值,通过查看与JIT相关的参数即可明白,我们可以暂时使用JIT编译。

首先,创建一个用于测试使用JIT编译的表格。

CREATE TABLE jit_test (a INTEGER, b TEXT);

INSERT INTO jit_test (a, b)
SELECT g, md5(g::text) FROM generate_series(1, 50000) AS g;

为了强制执行JIT编译,我们需要启用JIT编译并降低相关参数的阈值。

SET jit=on;
SET jit_above_cost=10;
SET jit_inline_above_cost=10;
SET jit_optimize_above_cost=10;

有了这个,就准备好使用JIT编译了。
在PostgreSQL 11中,JIT编译用于WHERE子句和聚合等功能。
(请参考以下手册中的详细信息)

    • 32.1.1. JIT Accelerated Operations

 

    https://www.postgresql.org/docs/11/static/jit-reason.html#JIT-ACCELERATED-OPERATIONS

因此,我們會在SQL語句中添加適當的WHERE子句,並執行該語句以查看執行計劃。

EXPLAIN ANALYZE SELECT * FROM jit_test WHERE a%2 = 1;
                                                  QUERY PLAN
---------------------------------------------------------------------------------------------------------------
 Seq Scan on jit_test  (cost=0.00..1167.00 rows=250 width=37) (actual time=71.657..77.408 rows=25000 loops=1)
   Filter: ((a % 2) = 1)
   Rows Removed by Filter: 25000
 Planning Time: 0.044 ms
 JIT:
   Functions: 2
   Options: Inlining true, Optimization true, Expressions true, Deforming true
   Timing: Generation 0.443 ms, Inlining 50.772 ms, Optimization 12.781 ms, Emission 7.972 ms, Total 71.969 ms
 Execution Time: 86.891 ms
(9 )

「JIT:」从下面的行可以看出,使用了JIT编译。
由于此次强行降低了阈值并使用了JIT编译,因此性能下降了与未使用JIT编译时相比。
这是因为超出开销的成本超过了JIT编译的加速效果。
接下来,我们将在下一节中调查和验证JIT编译在实际情况下的有效性。

我试图验证性能。

JIT编译执行查询不一定比常规查询执行快。
如果由于JIT编译导致的开销增加,它可能比常规查询更慢。
主要适用于由于CPU成为瓶颈而需要提速的查询,而I/O方面没有问题。
换句话说,适合包含复杂聚合或计算处理的SQL处理。

因此,我们选择了TPC-H基准测试进行本次测试。

引入TPC-H基准测试

TPC-H基准测试可以从TPC的网站上获得。
但是由于没有为PostgreSQL进行配置,因此需要进行调整。
本文将不介绍安装步骤。
如果您想了解更多详细信息,请参考参考网站上关于TPC-H的PostgreSQL安装链接。

本次我们使用了10GB的测试数据进行验证。

./dbgen -s 10

我们创建了以下环境用于验证。(由于TPC-H提供的SQL假设了TPCD模式中存在对象)

=# CREATE ROLE tpcd;
=# ALTER ROLE tpcd LOGIN SUPERUSER CREATEROLE CREATEDB CONNECTION LIMIT -1 PASSWORD 'password';
=# CREATE DATABASE tpcd OWNER tpcd;
=# \c tpcd tpcd
=# CREATE SCHEMA tpcd;

另外,我們使用以下的虛擬環境來進行驗證。

OSメモリCPUCentOS 7.44GB2コア

根据JIT编译的有无进行性能比较。

我们将使用TPC-H的查询1来比较使用和不使用JIT编译的性能。
首先是不使用JIT编译的EXPLAIN ANALYZE结果。
默认情况下,JIT使用是关闭的,但为了更容易理解,我们特意将JIT设置为OFF。

=# SET jit=off;
=# explain analyze
select
  l_returnflag,
  l_linestatus,
  sum(l_quantity) as sum_qty,
  sum(l_extendedprice) as sum_base_price,
  sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
  sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
  avg(l_quantity) as avg_qty,
  avg(l_extendedprice) as avg_price,
  avg(l_discount) as avg_disc,
  count(*) as count_order
from
  lineitem
where
  l_shipdate <= date '1998-12-01' - interval ':1' day
group by
  l_returnflag,
  l_linestatus
order by
  l_returnflag,
  l_linestatus
LIMIT 1;

                                                                            QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=2437688.60..2437688.94 rows=1 width=236) (actual time=68884.525..68885.261 rows=1 loops=1)
   ->  Finalize GroupAggregate  (cost=2437688.60..2437690.67 rows=6 width=236) (actual time=68884.524..68884.525 rows=1 loops=1)
         Group Key: l_returnflag, l_linestatus
         ->  Gather Merge  (cost=2437688.60..2437690.00 rows=12 width=236) (actual time=68884.493..68885.228 rows=4 loops=1)
               Workers Planned: 2
               Workers Launched: 2
               ->  Sort  (cost=2436688.57..2436688.59 rows=6 width=236) (actual time=68879.669..68879.670 rows=3 loops=3)
                     Sort Key: l_returnflag, l_linestatus
                     Sort Method: quicksort  Memory: 27kB
                     Worker 0:  Sort Method: quicksort  Memory: 27kB
                     Worker 1:  Sort Method: quicksort  Memory: 27kB
                     ->  Partial HashAggregate  (cost=2436688.33..2436688.50 rows=6 width=236) (actual time=68879.633..68879.641 rows=4 loops=3)
                           Group Key: l_returnflag, l_linestatus
                           ->  Parallel Seq Scan on lineitem  (cost=0.00..1437019.25 rows=24991727 width=25) (actual time=2.905..13461.643 rows=19995278 loops=3)
                                 Filter: (l_shipdate <= '1998-11-30 00:00:00'::timestamp without time zone)
                                 Rows Removed by Filter: 73
 Planning Time: 0.201 ms
 Execution Time: 68885.341 ms
(18 )
=# SET jit=on;
=# explain analyze
select
  l_returnflag,
  l_linestatus,
  sum(l_quantity) as sum_qty,
  sum(l_extendedprice) as sum_base_price,
  sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
  sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
  avg(l_quantity) as avg_qty,
  avg(l_extendedprice) as avg_price,
  avg(l_discount) as avg_disc,
  count(*) as count_order
from
  lineitem
where
  l_shipdate <= date '1998-12-01' - interval ':1' day
group by
  l_returnflag,
  l_linestatus
order by
  l_returnflag,
  l_linestatus
LIMIT 1;

                                                                            QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=2437688.60..2437688.94 rows=1 width=236) (actual time=55654.800..55658.101 rows=1 loops=1)
   ->  Finalize GroupAggregate  (cost=2437688.60..2437690.67 rows=6 width=236) (actual time=55278.626..55278.627 rows=1 loops=1)
         Group Key: l_returnflag, l_linestatus
         ->  Gather Merge  (cost=2437688.60..2437690.00 rows=12 width=236) (actual time=55278.556..55281.857 rows=4 loops=1)
               Workers Planned: 2
               Workers Launched: 2
               ->  Sort  (cost=2436688.57..2436688.59 rows=6 width=236) (actual time=55262.481..55262.482 rows=3 loops=3)
                     Sort Key: l_returnflag, l_linestatus
                     Sort Method: quicksort  Memory: 27kB
                     Worker 0:  Sort Method: quicksort  Memory: 27kB
                     Worker 1:  Sort Method: quicksort  Memory: 27kB
                     ->  Partial HashAggregate  (cost=2436688.33..2436688.50 rows=6 width=236) (actual time=55262.405..55262.413 rows=4 loops=3)
                           Group Key: l_returnflag, l_linestatus
                           ->  Parallel Seq Scan on lineitem  (cost=0.00..1437019.25 rows=24991727 width=25) (actual time=343.737..9535.259 rows=19995278 loops=3)
                                 Filter: (l_shipdate <= '1998-11-30 00:00:00'::timestamp without time zone)
                                 Rows Removed by Filter: 73
 Planning Time: 0.415 ms
 JIT:
   Functions: 35
   Options: Inlining true, Optimization true, Expressions true, Deforming true
   Timing: Generation 8.490 ms, Inlining 323.187 ms, Optimization 678.813 ms, Emission 392.651 ms, Total 1403.141 ms
 Execution Time: 55708.158 ms
(22 )

经过JIT编译,我们可以看到性能得到了改进。(虽然由于环境原因,不会明显变快…)
下面是每个方法执行5次时的比较结果。

実行時間(ms)1回目2回目3回目4回目5回目平均JITコンパイルなし62161.41263427.40465189.33974441.31562692.63265582.42JITコンパイルあり56242.27857135.67958272.94968390.39557561.05859520.47

通过使用JIT编译,可以加速执行复杂计算的SQL查询,尤其是在具备更大内存和CPU的环境下,JIT编译的影响会进一步增强。

参考网站

即时编译的详细信息和基准测试

    • PGCon 2017 (JIT-Compiling SQL Queries in PostgreSQL Using LLVM)

 

    • https://www.pgcon.org/2017/schedule/events/1092.en.html

 

    • PGConf 2017におけるJITコンパイルの講演です。

 

    • 従来との違いや、JITコンパイルの目的など詳しい情報が載っています。

PostgreSQL 11 and Just In Time Compilation of Queries
https://www.citusdata.com/blog/2018/09/11/postgresql-11-just-in-time/
JITコンパイルによるベンチマークテストの結果が載っています。

构建和验证系统

    • PostgreSQL 11 検証報告

 

    • https://www.sraoss.co.jp/tech-blog/pgsql/pg11report/

 

    • (→3.3.1. JIT コンパイルを使うためのビルド使うためのビルドうためのビルド)

 

    • PostgreSQL 11の様々な検証結果が載っています。

 

    • とりあえず11で何かできるのか、を知りたい方にオススメです。

KKIDA-GALAXY [PostgreSQL11のJITコンパイリングを試す]
http://kkida-galaxy.blogspot.com/2018/04/postgresql11-with-jit-01.html
JITコンパイル環境を構築手順として、実行コマンドとその結果など詳細に説明されています。
環境構築が上手くいかない方は、こちらをじっくりと参照すると良いと思います。

How to compile PostgreSQL 11 with support for JIT compilation on RHEL/CentOS 7
https://blog.dbi-services.com/how-to-compile-postgresql-11-with-support-for-jit-compilation-on-rhelcentos-7/
海外のサイトですが、今回の記事を執筆するに辺り、大変参考になりました。
導入手順からテスト方法まで丁寧に記載されています。
重要なコマンドとその結果は載っているため、英語が苦手な方もGoogle翻訳を利用すれば簡単に理解可能です。

PostgreSQL 11に搭載されるJITコンパイラ機能を動かしてみる
https://debug-life.net/entry/2928
構築から検証まで丁寧に記載されており、なにより参考情報が豊富です。
(参考にしたPostgreSQLのソース先も紹介されています)

在中国引入TPC-H的PostgreSQL。

    • TPC

 

    • http://www.tpc.org/default.asp

 

    • TPCの公式ページです。TPC-Hをはじめとしたベンチマークテストの入手やその説明文書が手に入ります。

PostgreSQL 9.6 with Parallel Query vs. TPC-H
http://rhaas.blogspot.com/2016/04/postgresql-96-with-parallel-query-vs.html
PostgreSQL 9.6上でTPC-Hの実施検証が載っています。リンク先のGitにPostgreSQL向けのTPC-Hクエリや、PostgreSQLへの導入方法など載っています。

DBGENを使って、PostgreSQLにTPC-H測定用データを格納

TPC-HをPostgreSQL上で実施する方法について、日本語で提供された情報です。

TPC-H Queries on PostgreSQL
http://myfpgablog.blogspot.com/2016/08/tpc-h-queries-on-postgresql.html
PostgreSQL上でTPC-Hを実施するための手順について記載されています。PostgreSQL向けに変換したSQLも載っています。

广告
将在 10 秒后关闭
bannerAds