• 1
  • 2
  • 3
  • 4
  • 5
mssql数据库问题 首 页  »  帮助中心  »  数据库  »  mssql数据库问题
如何利用系统缓存提高PostgreSQL操作效率
发布日期:2016-4-28 13:4:36

  最近试用pgfincore,对此做一个实验记录。pgfincore是将数据库对象提前加载到OS cache中,加快操作效率。当有一顶的物理更改的时候,pgfincore也会将其加载到缓存中。主要是提高查询效率的,当有频繁的缓存交换时,可能会被挤出缓存。

  PostgreSQL memory pgfincore

  一、环境介绍:

  •   OS:Centos 6.4 64bit
  •   Database:PostgreSQL9.4
  •   Memory:2G
  •   CPU:1核

  二、下载安装:

  在pgfoundry下载pgfincore-v1.1.1.tar.gz,,将源码解压到数据库源码下的contrib下。不要在其github上下载,目前应该有一些bug,最新版本为1.1.1,1.1.2在我试用的时候发现大部分函数无法使用。

  其次在我编译时一直出现如下所示的错误:

 

  [postgres@localhost pgfincore-1.1.1]$ make

  /bin/sh: pg_config: command not found

  make: pg_config: Command not found

  cp pgfincore.sql pgfincore--1.1.1.sql

  cp: cannot create regular file `pgfincore--1.1.1.sql': Permission denied

  make: *** [pgfincore--1.1.1.sql] Error 1

 

  所以在此我修改了一下Makefile文件,内容如下所示:

 

    # contrib/pgfincore/Makefile

  MODULE_big = pgfincore

  OBJS = pgfincore.o

  EXTENSION = pgfincore

  DATA = pgfincore--1.1.1.sql pgfincore--unpackaged--1.1.1.sql

  ifdef USE_PGXS

  PG_CONFIG = pg_config

  PGXS := $(shell $(PG_CONFIG) --pgxs)

  include $(PGXS)

  else

  subdir = contrib/pgfincore

  top_builddir = ../..

  include $(top_builddir)/src/Makefile.global

  include $(top_srcdir)/contrib/contrib-global.mk

 

  现在进行make,即可,如下所示:

 

   [postgres@localhost pgfincore-1.1.1]$ make

  gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -g -O2 -fpic -I. -I. -I../../src/include -D_GNU_SOURCE -c -o pgfincore.o pgfincore.c

  pgfincore.c: In function ‘pgsysconf’:

  pgfincore.c:227: warning: implicit declaration of function ‘heap_form_tuple’

  pgfincore.c:227: warning: assignment makes pointer from integer without a cast

  pgfincore.c: In function ‘pgfadvise’:

  pgfincore.c:477: warning: assignment makes pointer from integer without a cast

  pgfincore.c: In function ‘pgfadvise_loader’:

  pgfincore.c:710: warning: assignment makes pointer from integer without a cast

  pgfincore.c: In function ‘pgfincore’:

  pgfincore.c:1016: warning: assignment makes pointer from integer without a cast

  gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -g -O2 -fpic -shared -o pgfincore.so pgfincore.o -L../../src/port -L../../src/common -Wl,--as-needed -Wl,-rpath,'/opt/hg3.0/lib',--enable-new-dtags

  [postgres@localhost pgfincore-1.1.1]$ make install

  /bin/mkdir -p '/opt/hg3.0/lib/postgresql'

  /bin/mkdir -p '/opt/hg3.0/share/postgresql/extension'

  /bin/mkdir -p '/opt/hg3.0/share/postgresql/extension'

  /usr/bin/install -c -m 755 pgfincore.so '/opt/hg3.0/lib/postgresql/pgfincore.so'

  /usr/bin/install -c -m 644 pgfincore.control '/opt/hg3.0/share/postgresql/extension/'

  /usr/bin/install -c -m 644 pgfincore--1.1.1.sql pgfincore--unpackaged--1.1.1.sql '/opt/hg3.0/share/postgresql/extension/'

  [postgres@localhost pgfincore-1.1.1]$

 

  三、实验记录:

  1、安装,代码如下所示:


  图1

  2、准备工作:记录比较使用pgfincore前后的性能差,使用插件pg_stat_statments记录每条sql的使用时间。

  其次将shared_buffer改为16mb,减少其对pgfincore的影响。


    图2

  3、建立表testmem,分别在使用与不适用pgfincore情况下进行select, update, delete的操作,并对比执行时间,为了更好的去作比较,建立三张表:

  • testmem1
  • testmem2
  • testmem3

   分别进行三种操作进行对比。并插入相同的数据。如下所示:

  [postgres@localhost bin]$ ./psql

  psql (9.4.5)

  Type "help" for help.

  postgres=# \d

  No relations found.

  postgres=# create table testmem1(t1 int, t2 text, t3 text, t4 bigint, t5 text, t6 text, t7 varchar, t8 char(22), t9 numeric);CREATE TABLE

  postgres=# create table testmem2(t1 int, t2 text, t3 text, t4 bigint, t5 text, t6 text, t7 varchar, t8 char(22), t9 numeric);

  CREATE TABLE

  postgres=# create table testmem3(t1 int, t2 text, t3 text, t4 bigint, t5 text, t6 text, t7 varchar, t8 char(22), t9 numeric);

  CREATE TABLE

  postgres=# insert into testmem1 select generate_series(1,999999), 'wangshuo'||generate_series(1,999999)::text||random()::text, generate_series(1,999999)::text||'sure',generate_series(1,999999), random()::text,random()::text,random()::text,'liuyuanyuan', generate_series(1,999999);

  INSERT 0 999999

  postgres=# select pg_relation_size('testmem1')/1024/1024||'MB';

  ?column?

  ----------

  166MB

  (1 row)

  postgres=# insert into testmem2 select generate_series(1,999999), 'wangshuo'||generate_series(1,999999)::text||random()::text, generate_series(1,999999)::text||'sure',generate_series(1,999999), random()::text,random()::text,random()::text,'liuyuanyuan', generate_series(1,999999);

  INSERT 0 999999

  postgres=# insert into testmem3 select generate_series(1,999999), 'wangshuo'||generate_series(1,999999)::text||random()::text, generate_series(1,999999)::text||'sure',generate_series(1,999999), random()::text,random()::text,random()::text,'liuyuanyuan', generate_series(1,999999);

  INSERT 0 999999

  postgres=# select pg_relation_size('testmem2')/1024/1024||'MB'; ?column?

  ----------

  166MB

  (1 row)

  postgres=# select pg_relation_size('testmem3')/1024/1024||'MB';

  ?column?

  ----------

  166MB

  (1 row)

  postgres=#

  三种操作性能对比,如下所示:


                                                                     图3

  使用pgfincore前:通过查询表pg_stat_statments查看三种操作时间,如下所示:


                                                              图4

  使用pgfincore后:通过查询表pg_stat_statments查看三种操作时间(重启机器后,重新建库,重新建表、插数据),如下所示:


                                                      图5

  明显看出当执行select时速度提升明显,其他的时间提升并不明显,这是因为数据还需要进行IO操作,因此在这里速度提升应该仅仅是读入的时间节省掉了。如下所示:

    postgres=# select pgfadvise_willneed('testmem1');

  -[ RECORD 1 ]------+-------------------------------------

  pgfadvise_willneed | (base/13003/16384,4096,42554,279311)

  postgres=# select * from pgfincore('testmem1');

  -[ RECORD 1 ]-+-----------------

  relpath | base/13003/16384

  segment | 0

  os_page_size | 4096

  rel_os_pages | 42554

  pages_mem | 42554

  group_mem | 1

  os_pages_free | 279317

  databit |

  postgres=# select count(*) from testmem1 where t1 < 99999 and t1 > 12;

  -[ RECORD 1 ]

  count | 99986

  postgres=# insert into testmem1 select generate_series(1,9999), 'wangshuo'||generate_series(1,9999)::text||random()::text, generate_series(1,9999)::text||'sure',generate_series(1,9999), random()::text,random()::text,random()::text,'liuyuanyuan', generate_series(1,9999);

  INSERT 0 9999

  postgres=# select * from pgfincore('testmem1');-[ RECORD 1 ]-+-----------------

  relpath       | base/13003/16384

  segment       | 0

  os_page_size  | 4096

  rel_os_pages  | 42980

  pages_mem     | 42980

  group_mem     | 1

  os_pages_free | 277433

  databit       |

  postgres=# select pg_relation_size('testmem1');

  -[ RECORD 1 ]----+----------

  pg_relation_size | 176046080

  postgres=# select 42980*4096;

  -[ RECORD 1 ]-------

  ?column? | 176046080

  postgres=# insert into testmem1 select generate_series(1,999999), 'wangshuo'||generate_series(1,999999)::text||random()::text, generate_series(1,999999)::text||'sure',generate_series(1,999999), random()::text,random()::text,random()::text,'liuyuanyuan', generate_series(1,999999);

  INSERT 0 999999

  postgres=# select * from pgfincore('testmem1');

  -[ RECORD 1 ]-+-----------------

  relpath | base/13003/16384

  segment       | 0

  os_page_size  | 4096

  rel_os_pages  | 85532

  pages_mem     | 6188

  group_mem     | 22

  os_pages_free | 403050

  databit       |

  postgres=#

  上面所示的这个实验验证了willneed会将小部分新加入的数据加载到cache中,能快速的定位查找,但当插入数据量较大时,就不会及时的写入到cache中了。

  总结:pgfincore目前适用于数据量非常大、更新不频繁、更新量较小的表去加载到缓存中,有助于提高应用效率。

  四、插件函数介绍:

  接下来对函数进行介绍,并对所有函数进行操作实验。

  1、pgsysconf:

  这个函数输出OS block的大小(os_page_size),OS中剩余的page数(os_pages_free)和OS拥有的page总数(os_total_pages)。如下所示:


                                       图6

  2、pgsysconf_pretty:

  这个函数与上面的一样,仅仅是输出更易懂些。如下所示:  


                                                                                       图7

  3、pgfadvise_willneed:

  这个函数是

  输出文件名(relpath),OS block大小(os_page_size),对象占用系统page数(rel_os_pages),OS剩余的page数(os_pages_free)。如下所示:


                                                              图8

  4、pgfadvise_dontneed:

  这个函数对当前对象设置dontneed标记。意思就是当操作系统需要释放内存时优先释放标记为dontneed的pages。输出的意义与面一致,就不多做介绍了。如下所示:


                                                                                  图9

  5、pgfadvise_NORMAL、pgfadvise_SEQUENTIAL、pgfadvise_RANDOM:

  与pgfadvise_dontneed大同小异,分别将对象标记为:

  •     normal
  •     sequential
  •     random

      意思按照字面意思理解就可以了。

  其实pgfadvise是一个单独的函数,参数是relname,fork,action,含义分别为对象名、文件分支名以及行为id,上面的3、4、5函数都是输入不同参数而设置的函数,其中willneed、dontneed、normal、sequential、random的值分别是10、20、30、40、50,且默认fork为main,即表文件。

  这里的pgfadvise主要调用了Linux下的函数posix_fadvise,标记值也是posix_fadvise所需要的。

  6、pgfincore:

  这个函数是是提供对象在操作系统缓存中的信息的。

  它分为三个函数,参数分别为:

  •    (relname, fork, getdatabit)
  •    (relname, getdatabit)
  •    (relname)

    三个参数意思为对象名,进程名(这个地方默认是main),是否要显示databit(很长,注意显示),第一个函数需要全部输入,第二个函数默认fork为main,第三个函数默认fork为main,getdatabit为false。

  它输出的是文件位置及名称(relpath),文件顺序(segment),OS page或者block大小(os_page_size),对象占用系统缓存需要的页面个数(rel_os_pages),对象已经占用缓存页面个数(pages_mem),在缓存中连续的页面组的个数(group_mem),OS剩余的page数(os_pages_free),加载信息的位图(databit)。如下所示:


                                                                                        图10

  这个函数可以对页面缓存直接进行两方面的作用。所以,它能通过页面的位图在缓存中来对页面进行加载或卸载。

  它分为两个函数与上边的类似,就是设置缺省值,的输入参数是(relname, fork, segment, load, unload, databit)与(relname, segment, load, unload, databit),分别是对象名,文件分支名,文件序号,是否加载,是否卸载,位图信息。第二个函数默认fork为main。

  它输出的是物理文件名及path(relpath),OS page或block大小(os_page_size), OS中剩余的page数(os_pages_free),加载的page数(pages_load),卸载的page数(pages_unload)。如下所示:


                                                                           图11

   后面会更新关于mssql效率的相关问题,关注mssql的朋友敬请期待。