MySQL内核月报 2015.02-PgSQL · 特性分析· pg_prewarm

PostgreSQL内核中引入了一个很有意思的插件,pg_prewarm。它可以用于在系统重启时,手动加载经常访问的表到操作系统的cache或PG的shared buffer,从而减少检查系统重启对应用的影响。这个插件是这个通过这个patch加入PG内核的。 pg_prewarm的开发者在设计pg_prewarm时,把它设计成一个执行单一任务的工具,尽求简单,所以我们看到的pg_prearm功能和实现都非常简单。下面我们对它进行性能实测并分析一下它的实现。

基本信息

利用下面的语句可以创建此插件:


实际上,创建插件的过程只是用下面的语句创建了pg_prewarm函数。这个函数是此插件提供的唯一函数:


函数的第一个参数是要做prewarm的表名,第二个参数是prewarm的模式(prefetch模式表示异步预取到操作系统cache;read表示同步预取;buffer则表示同步读入到PG的shared buffer),第三个参数是relation fork的类型(一般用main,其他类型有visibilitymap和fsm,参见[1][2]),最后两个参数是开始和结束的block number(一个表的block number从0开始,block总数可以通过pg_class系统表的relpages字段获得)。

性能实测

再来看看,这个prewarm性能上能达到多大效果。我们先将PG的shared buffer设为2G,OS总的memory有7G。然后创建下面的大小近1G的表test:



在每次都清掉操作系统cache和PG的shared buffer的情况下,分别测试下面几种场景:

1)不进行pg_prewarm的情况:


可以看到,近1G的表,全表扫描一遍,耗时22秒多。

2)下面我们先做read这种模式的prewarm,test表的数据被同步读入操作系统cache(pg_prewarm返回的是处理的block数目,此处我们没指定block number,也就是读入test的所有block),然后再做全表扫:



时间降至8秒多!这时反复执行全表扫描,时间稳定在8秒多。

3)再尝试buffer模式:



比read模式时间略少,但相差不大。可见,如果操作系统的cache够大,数据取到OS cache还是shared buffer对执行时间影响不大(在不考虑其他应用影响PG的情况下)。

4)最后尝试prefetch模式,即异步预取。这里,我们有意在pg_prewarm返回后,立即执行全表查询。这样在执行全表查询时,可能之前的预取还没完成,从而使全表查询和预取并发进行,缩短了总的响应时间:



可以看到,总的完成时间是9秒多,使用pg_prewarm做预取大大缩短了总时间。因此在进行全表扫描前,做一次异步的prewarm,不失为一种优化全表查询的方法。

实现

pg_prewarm的代码只有一个pg_prewarm.c文件。可以看出,prefetch模式下,对于表的每个block,调用一次PrefetchBuffer,后面的调用为:


可见,它是最终调用posix_fadvise,把读请求交给操作系统,然后返回,实现的异步读取。

而在read和buffer模式(调用逻辑分别如下)中,最终都调用了系统调用read,来实现同步读入OS cache和shared buffer的(注意buffer模式实际上是先读入OS cache,再拷贝到shared buffer):



问题

可能有人比较疑惑:执行1次select * from 不就可以将表的数据读入shared buffer和OS cache而实现预热了吗?岂不是比做这样一个插件更简单?实际上,对于较大的表(大小超过shared buff的1/4),进行全表扫描时,PG认为没必要为这种操作使用所有shared buffer,只会让其使用很少的一部分buffer,一般只有几百K,详细描述可以参见关于BAS_BULKREAD策略的代码README)。所以,预热大表是不能用一个查询直接实现的,而pg_prewarm正是在这方面大大方便了用户。

时间: 2025-01-05 19:33:40

MySQL内核月报 2015.02-PgSQL · 特性分析· pg_prewarm的相关文章

MySQL内核月报 2015.01-MySQL · 新增特性· DDL fast fail

背景 项目的快速迭代开发和在线业务需要保持持续可用的要求,导致MySQL的ddl变成了DBA很头疼的事情,而且经常导致故障发生.本篇介绍RDS分支上做的一个功能改进,DDL fast fail.主要解决:DDL操作因为无法获取MDL排它锁,进入等待队列的时候,阻塞了应用所有的读写请求问题. MDL锁机制介绍 首先介绍一下MDL(METADATA LOCK)锁机制,MySQL为了保证表结构的完整性和一致性,对表的所有访问都需要获得相应级别的MDL锁,比如以下场景: session 1对t1表做查询

MySQL内核月报 2015.02-PgSQL · 特性分析· Replication Slot

PostgreSQL 9.4 已于2014年底正式发布了(阿里云的RDS将支持PG 9.4).在这个版本,我们看到了像Jsonb, Logical Decoding, Replication Slot等新功能.对于Replication Slot,文档上介绍的不多,乍一看让人比较难理解是做什么的.其实,Replication Slot的出现,主要是为最终在PG内核实现逻辑复制和双向复制铺路的(目前,逻辑和双向复制在内核中还缺少很多核心功能点,需要借助BDR插件,见PG官方wiki ,引入Repl

MySQL内核月报 2015.03-MySQL · 优化限制· MySQL index_condition_pushdown

背景 MySQL 5.6 开始支持index_condition_pushdown特性,即server层把可以在index进行filter的谓词传递给引擎层完成过滤,然后结果返回到server. 工作方式 下面看一下InnoDB的处理方式: 通过设置set global optimizer_switch= "index_condition_pushdown=ON"来启用这个特性. 例如: 1. 评估 在执行计划评估阶段,通过push_index_cond函数把index filter谓

MySQL内核月报 2015.02-MariaDB · 特性分析· Per-query variables

自MariaDB 10.1.2起,MariaDB提供了一种"Per-query variables的方式来为Query设置语句级变量,通过 SET STATEMENT 语句可以为接下来要执行的语句设置一些系统变量值. 语法 SET STATEMENT var1=value1 [, var2=value2, ...] FOR <statement> varN是一个系统变量,valueN是一个常量值.但是有部分变量是不支持的,在这个章节的末尾列出了所有不支持的变量. 一条 "S

MySQL内核月报 2015.02-MariaDB · 特性分析· 表/表空间加密

Google向MariaDB 10.1.13(暂未Release)贡献了这个补丁,可以对表/表空间进行加密. 加密过的表可以防止某些非授权用户访问或偷取磁盘然后通过访问原始数据文件来偷取数据.当然,假设你已经把密钥文件存储在另一个系统上.但是,使用加密可能会降低差不多10%的性能.目前,只有XtraDB/InnoDB引擎能完全支持加密. MariaDB在InnoDB/XtraDB中支持两种方式的加密: Table encryption(表级加密): 只有在创建时指定 PAGE_ENCRYPTIO

MySQL内核月报 2015.02-TokuDB · 特性分析· 日志详解

TokuDB的日志跟InnoDB不一样,它有两类文件: redo-log文件(以.tokulog[序号]为扩展名) rollback日志文件(tokudb.rollback) 接下来就简单唠唠这两类文件的内部细节. 1) redo-log 记录的不是页而是对Fractal-Tree索引的操作日志. log格式: content里记录的是具体的日志内容,比如insert操作,content就是: TokuDB在做恢复的时候,会找到上次checkpoint时的LSN位置,然后读取log逐条恢复. 为

MySQL内核月报 2015.01-TokuDB·特性分析· Optimize Table

来自一个TokuDB用户的"投诉": https://mariadb.atlassian.net/browse/MDEV-6207 现象大概是: 用户有一个MyISAM的表test_table: 转成TokuDB引擎后表大小为92M左右: 执行"OPTIMIZE TABLE test_table": 再次执行"OPTIMIZE TABLE test_table": 继续执行: 基本稳定在这个大小. 主索引从47M-->63M-->79

MySQL内核月报 2015.03-MySQL · 答疑释惑· 并发Replace into导致的死锁分析

测试版本:MySQL5.6.23 测试表: 背景 Replace into操作可以算是比较常用的操作类型之一,当我们不确定即将插入的记录是否存在唯一性冲突时,可以通过Replace into的方式让MySQL自动处理:当存在冲突时,会把旧记录替换成新的记录. 我们先来理一下一条简单的replace into操作(如上例所示)的主要流程包括哪些. Step 1. 正常的插入逻辑 首先插入聚集索引记录,在上例中a列为自增列,由于未显式指定自增值,每次Insert前都会生成一个不冲突的新值. 随后插入

MySQL内核月报 2015.03-MySQL · 捉虫动态· pid file丢失问题分析

现象 mysql5.5,通过命令show variables like '%pid_file%'; 可以查到pid文件位置,例如/home/mysql/xx.pid.但发现在此目录下找不到此pid文件. 背景知识 mysql pid文件记录的是当前mysqld进程的pid. 通过mysqld_safe启动mysqld时,mysqld_safe会检查PID文件,未指定PID文件时,pid文件默认名为$DATADIR/`hostname`.pid pid文件不存在,不做处理 文件存在,且pid已占用