postgresql成本因子调整

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介: postgresql因子的调整主要有这四个cpu_tuple_cost,random_page_cost,cpu_index_tuple_cost,cpu_operator_cost。这四个因子的值影响着计划中的cost值,这个因子大小的是否正确很大程度的影响着执行计划走的是否正确

    postgresql因子的调整主要有这四个cpu_tuple_cost,random_page_cost,cpu_index_tuple_cost,cpu_operator_cost。这四个因子的值影响着计划中的cost值,这个因子大小的是否正确很大程度的影响着执行计划走的是否正确。
    1.安装systemtap
    需要用到的工具是systemtap,在安装systemtap前请先进行如下操作
    
image

之后安装相同版本号的kernel-devel,kernel-debuginfo,kernel-debuginfo-common(注意包括小版本号一定要相同)

image

image

    至于去哪找这些rpm包我是从这里找到的http://rpm.pbone.net/index.php3。如果实在找不到同版本的这3个安装包建议换个版本的系统吧。之后安装systemtap,

image
   
 如果安装完后应该是有这些包

image
  

  下面输入这个

    [root@bogon ~]# stap -ve 'probe begin { log("hello world") exit() }'测试下是否成功安装
    
image
  

 2.安装postgresql

    systemtap安装成功后开始安装postgresql,我安装的版本的9.3,源码安装的
    
image

    安装步骤,就解压后到目录中执行
    [postgres@bogon postgresql-9.3.0]$ ./configure --prefix=/home/postgres/data --enable-dtrace

image
  
  之后就是
    [postgres@bogon postgresql-9.3.0]$ make && make install
    完成后运行下
    [postgres@bogon bin]$ pg_config --configure
    
image
   

 确保一定要有--enable-dtrace这个东西,这个就是允许探针访问pg的选项。

    接下来就是初始化数据库:initdb -D 数据库目录。
    [postgres@bogon data]$ pg_ctl start -D pgdata 启动数据库。
 
   3.调整因子前环境的配置
    创建测试用表:
    create table test(a int,b int);
    插入数据:(需要数据有一定的离散性)
    insert into test select random()1000000,random()1000000 from generate_series(1,1000000);
    创建索引:
    create index index_a on test(a);
    更新统计信息:
    analyse;
    将数据写入磁盘:
    checkpoint;
    关闭数据库:
    pg_ctl stop -D pgdata/
    清空操作系统缓存
    [root@bogon ~]# sync; echo 3 > /proc/sys/vm/drop_caches
    下面就要使用stap了,具体代码如下
    stap -e '
    global a
    probe process("/home/postgres/data/bin/postgres").mark("query__start") {
        delete a
        println("query__start ", user_string($arg1), "pid:", pid())
    }
    probe vfs.read.return {
        t = gettimeofday_ns() - @entry(gettimeofday_ns())
        # if (execname() == "postgres" && devname != "N/A")
        a[pid()] <<< t
    }
    probe process("/home/postgres/data/bin/postgres").mark("query__done") {
        if (@count(a[pid()])) 
        printdln("**", pid(), @count(a[pid()]), @avg(a[pid()]))
        println("query__done ", user_string($arg1), "pid:", pid())
        if (@count(a[pid()])) {
        println(@hist_log(a[pid()]))
        #println(@hist_linear(a[pid()],1024,4096,100))
    }
  delete a
}' -x 2808
    这个a是一个数组中存着,pid号,多少次读取数据块,读取数据块的平均时间,stap监控着postgres这个进程,vfs.read.return这个函数是得到块设备读入一个数据块的时间,并存入数组a中,最后返回pid号和读取块的次数和平均读取时间。-x 后面的数字要设置为你监控的pid号
    postgres=# select pg_backend_pid();
    
image
    
    4.调整成本因子
    
    4.1调整全表扫描的相关因子
    首先得到会话的pid号之后运行前面呢段代码:
    image

  

  确定模块是否加载上了

    [root@bogon ~]# lsmod |grep stap
    image

   

 执行如下语句:

    postgres=# explain (analyze,verbose,costs,buffers,timing) select * from test ;
    
image

    查看下stap的结果:
    
image
  

  最终看的结果就是a的数组中存储的值就是18782**4439**148019(第一项pid号,第二个读取块次数,第三个读取一次的平均时间),呢个value和count的图就是读取时间和次数的直方图。

    
    
    补充一个图还要查下pg_class中的relpages的数量,这个是整个表存储的页面数
    postgres=# select relpages from pg_class where relname='test';
    
image
   

 全表扫描的计算公式是什么呢?

    cost(真实执行时间)=seqscan_costrelpages+cpu_tuple_costlines(表的行数)
    根据上面的图可以得到如下结果:
    cost=677.602
    seq_page_cost=148019*10^-6
    relpages=4425
    lines=1000000
    由这些值可得
    cpu_tuple_cost=0.000022617925
    seqscan_cost=0.148019
    这两个值先记录下来。
    我们可以set seq_page_cost=0.148019;set cpu_tuple_cost=0.000022617925;在进行全表扫描看下结果。
    重复之前操作清理下系统缓存:
    [root@bogon ~]# sync; echo 3 > /proc/sys/vm/drop_caches
    重启数据库;
    设置这两个因子
    重新查询下之前的语句
    
image
   

 你会发现cost值是不是和真实值很接近呢。cpu_tuple_cost和sea_page_cost已经校准完成啦。

    
    4.2调整索引相关的成本因子
    重复之前调全表扫描因子的步骤,这里不再赘述。
    首先设置cpu_tuple_cost=1,random_page_cost=1,cpu_index_tuple_cost=1,cpu_operator_cost=1。设置的原因之后在进行解释。
    
image
  

  关闭全表扫描set enable_seqscan =off;set enable_bitmapscan =off;

    执行如下语句:explain (analyze,verbose,costs,buffers,timing) select * from test where a>489963;
    
image
    
    stap结果:
    
image

    索引扫描的代价计算公式是:
    cost=random_page_costblocks+cpu_tuple_costline1+cpu_index_tuple_costline2+cpu_operator_costline2
    cost=9283.272
    random_page_cost=1.534983
    line1=508823
    line2=?
    blocks=?
    这个line2就和之前设置所有因子都是1就有关系了,我们可以通过调整cpu_operator_cost为2其他因子不变,两个得到的cost结果相减就可以得到line2了,blocks也是同理通过调整random_page_cost来得到结果。
    image

   

 line2=2041453-1532460=508993

    
    
image
 
 blocks=1538282-1532460=5822
    2cpu_operator_cost=cpu_index_tuple_cost
    综上可得出
    cpu_operator_cost=0.00548671355463809587
    cpu_index_tuple_cost=0.01097342710927619174
    random_page_cost=1.534983
    我们再来重新调整完因子后再测试下语句
    
image
   

 和真实值有点偏差,可能是因为systemtap会占用一定的cpu资源,我这个是关闭systemtap进行测试的。

    
    
    最终结果是
    cpu_operator_cost=0.00548671355463809587
    cpu_index_tuple_cost=0.01097342710927619174
    random_page_cost=1.534983
    cpu_tuple_cost=0.000022617925
    seqscan_cost=0.148019

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
2月前
|
SQL 存储 关系型数据库
Mysql内核查询成本计算
Mysql内核查询成本计算
|
8月前
|
SQL 存储 关系型数据库
【MySQL进阶-06】深入理解mysql的内核查询成本计算
【MySQL进阶-06】深入理解mysql的内核查询成本计算
115 0
|
10月前
|
存储 SQL JSON
MySQL查询为什么选择使用这个索引?——基于MySQL 8.0.22索引成本计算
多个索引之中,MySQL为什么选择这个索引?本文带你进行计算分析
100 0
MySQL查询为什么选择使用这个索引?——基于MySQL 8.0.22索引成本计算
|
11月前
|
存储 缓存 算法
一文带你了解MySQL之基于成本的优化
我们之前老说MySQL执行一个查询可以有不同的执行方案,它会选择其中成本最低,或者说代价最低的那种方案去真正的执行查询,怎么就带大家详细了解一下
67 0
|
11月前
|
存储 JSON 算法
一文带你了解MySQL之基于成本的优化
我们之前老说MySQL执行一个查询可以有不同的执行方案,它会选择其中成本最低,或者说代价最低的那种方案去真正的执行查询,怎么就带大家详细了解一下
114 0
|
SQL 存储 监控
【MySQL从入门到精通】【高级篇】(二十二)慢查询日志分析,SHOW PROFILE查看SQL执行成本
上一篇文章我们介绍数据库的优化步骤【MySQL从入门到精通】【高级篇】(二十一)数据库优化步骤_查看系统性能参数,其中,说到了通过开启慢查询日志来分析慢查询的SQL。这篇文章就是具体来介绍如何开启慢查询日志以及如何分析慢查询日志。
214 0
【MySQL从入门到精通】【高级篇】(二十二)慢查询日志分析,SHOW PROFILE查看SQL执行成本
|
SQL 存储 关系型数据库
MYSQL 索引成本计算,为什么MYSQL预判后选择了错误索引?
IO 成本: 即从磁盘把数据加载到内存的成本,默认情况下,读取数据页的 IO 成本是 1,MySQL 是以页的形式读取数据的,即当用到某个数据时,并不会只读取这个数据,而会把这个数据相邻的数据也一起读到内存中,这就是有名的程序局部性原理,所以 MySQL 每次会读取一整页,一页的成本就是 1。所以 IO 的成本主要和页的大小有关
219 0
|
SQL 移动开发 关系型数据库
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)|学习笔记
快速学习PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)
545 0
PostgreSQL 执行计划,成本公式解说,代价因子校准,自动跟踪SQL执行计划(三)|学习笔记
|
存储 SQL 缓存
连接查询成本(2)---mysql进阶(四十二)
连接查询成本(2)---mysql进阶(四十二)
|
SQL 存储 缓存
连接查询成本(2)---mysql进阶(四十二)
连接查询成本(2)---mysql进阶(四十二)