一、前言
PostgreSQL之强大,在于社区生态之蓬勃,在于可扩展性之完美,PostgreSQL支持上百种插件,通过插件,它的功能日渐丰富且能力日渐强大,其他数据库能做的,我PostgreSQL照样能做(未来之趋势)。前久看了微信公众号“非法加冯”上的一篇文章《PostgreSQL正在吞噬数据库世界》,PostgreSQL正在数据库大陆模板图上探索新的领土,拓展自己的大陆模板图,插件就是它征服数据库大陆的武器,说实话,我有点小兴奋,我也希望PG实现数据库的大一统,让人们的智慧放在数据库新功能新领域的探索之上,让数据库技术更快速的发展,PostgreSQL之插件,如虎添翼。
《PostgreSQL正在吞噬数据库世界》的作者也整理PostgreSQL目前可用的插件,并放在Pigsty|扩展网站上,当我浏览作者提供的插件览表时(该览表在其微信公众号的《PG隆中对,一个PG三个核,一个好汉三百个帮》文章中有展示),当看到count_distinct插件时,光从字面理解,我略带激动,我想这个插件可能解决了前久所遇到的一个SQL性能问题,人最近越是在想什么,那最近对该事的留意度就越高。
带着探索的心态,我也想测试count_distinct插件是否好用,是否真的解决了我所遇到的问题,同时整理了如何向PostgreSQL中添加插件的操作步骤。
前久遇到一个性能问题,在对表的某个字段去重并做count操作时,SQL select count(distinct col1) from test1的执行性能比select count(*) from (select distinct col1 from test1) a还差。这不难免会引起性能问题,业务厂商或者用户更趋于使用前者来满足自己的需求。于是我做了更深入的测试(数据库版本14.2),发现:当col1字段值去重之后的数量与基表总行数之比逐渐升高时,前者的执行性能逐渐升高,后者的执行性能逐渐降低,当比值达到某个临界点时前者的执行性能开始高于后者,反之亦然。在我的测试中,当这个比值为1/50左右时,后者的执行性能优于前者,当该比值更低时,这种性能更明显,反之亦然。所以得出一个简单的结论,当列值去重之后的数据量远小于基表数量时,推荐使用后者来满足需求。但这不是我想要的,我期望count(distinct col1)任何情况下性能总是最好的,简单即是性能最优(过于理想化了),但这确实也是大家所期望的吧,谁也不想在有简单SQL就可以实现需求的情况下,去考虑一个更为复杂的SQL来提升性能。于是初见count_distinct插件,我是略带兴奋的,但是否能够让我高兴到底呢?我对其进行了测试。
通过从前文提供的网站中下载了count_distinct插件,并添加到自己的测试环境中。功能测试方面,count_distinct插件局限性还是较大的,在字段处理上不支持char、varchar类型,我就已经开始失落了,需要做去重计数操作的字段类型大多数是char或者varchar。count_distinct插件的官网:https://github.com/tvondra/count_distinct,官网解释仅支持处理定长的数据类型,int、boolean、枚举类型还是支持的。性能测试方面:正如官网所说,从执行计划来看count_distinct(col1)相比于count(distinct col1)将排序操作给去除掉了,从而使得性能得到了提升,然而当col1字段值去重之后的结果集数与基表行数之比越高时,即字段中重复值不多时,count(distinct col1)的性能优于count_distinct(col1),反之,当比值越低时,性能不如select count(*) from (select distinct col1 test1) a;但有一点需要关注,count_distinct去除排序操作,降低了内存耗用,也算是一个优点。
针对上述结论,可能在大数据集上体现更为明显。本文主要展示如何为PostgreSQL添加插件,测试的流程及步骤就不深入展开,仅提供测试SQL,如下所示:
-- count(*) from (distinct col1) explain (analyze,buffers) select count(*) from (select distinct generate_series(1,200000) id from generate_series(1,50)) a; -- count(distinct col1) explain (analyze,buffers) select count(distinct id) from (select generate_series(1,200000) id from generate_series(1,50)) a; -- count_distinct(col1) explain (analyze,buffers) select count_distinct(id) from (select generate_series(1,200000) id from generate_series(1,50)) a;
复制
二、添加插件
以count_distinct插件为例子:
# 1.切换到PostgreSQL数据库操作系统用户,并创建一个用于存放插件的目录 su - postgres mkdir extension # 2.进入目录,并下载count_distinct插件源码 cd extension git clone https://github.com/tvondra/count_distinct.git # 3.进入到count_distinct目录,对源码进行编译 cd count_distinct make # 4.将生成的库文件count_distinct.so拷贝至数据库软件安装目录下的lib/postgresql下## (本测试用例数据库软件安装目录为/opt/software/pg14) cp count_distinct.so /opt/software/pg14/lib/postgresql/ # 5.将相关SQL文件拷贝至插件目录 ## 插件目录默认为:数据库软件目录/share/postgresql/extension cp count_distinct.control sql/* /opt/software/pg14/share/postgresql/extension/ # 6.连接数据库并创建插件 psql create extension count_distinct;
复制
到此,向PG中添加插件的操作步骤就已经结束了!!