PostgreSQL代价全解及其查询优化

explain语法

下面是postgresql.conf中默认的一些代价因子。
在这里插入图片描述
在这里插入图片描述
analyze这个关键字是将语句真正的执行。如果只有shared_buffer,说明没有从外部命中数据。有read的话,说明是从磁盘等外部环境读取了数据。
在这里插入图片描述
在这里插入图片描述

三大连接

在postgresql.conf中开关三大连接
在这里插入图片描述

嵌套连接

在这里插入图片描述

在这里插入图片描述

哈希连接

在这里插入图片描述
在这里插入图片描述

合并连接

在这里插入图片描述
在这里插入图片描述

explain成本计算

在这里插入图片描述
准备测试数据:
在这里插入图片描述
在这里插入图片描述
如上图我们可以看到,reltuples代表总共有多少条记录,relpages是表示总共有多少页。
在这里插入图片描述
结合上下图,来看看这全表扫描是怎么算的。
在这里插入图片描述
再来看看下面这种情况,id<100中的小于号是对应了某个函数的,我们应该在估算成本时,加上函数的开销。
在这里插入图片描述
我们来查一查小于符号对应的函数。
在这里插入图片描述
看看上图,有那么多函数,到底哪一个是比较int类型的小于号呢?
在这里插入图片描述
下面箭头所指函数就是对应函数。
在这里插入图片描述
然后查一下这个函数的成本为1
在这里插入图片描述
然后看看总的1693是怎么算的?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

explain行数评估

从bucket评估行数

在这里插入图片描述
在这里插入图片描述
我们用真实例子测试一下;
下图框住部分有100个bucket,bucket数量可以在postgresql中设置,默认是100.
在这里插入图片描述
然后这个row跟bucket有关。
在这里插入图片描述
在这里插入图片描述

从MCV(most common values)评估行数

在这里插入图片描述
来举一个真实例子,我继续插入10万条数据。
在这里插入图片描述
我们来看看现在这个rows是怎么评估的?
在这里插入图片描述
现在箭头所指的两个属性有值了。
在这里插入图片描述
现在有20万条记录
在这里插入图片描述
然后看下面怎么计算rows
在这里插入图片描述

从MCV和distinct值中评估行数

在这里插入图片描述
继续举例:
在这里插入图片描述
然后计算distinct的值:
在这里插入图片描述
然后计算单个值的选择性:
在这里插入图片描述
最终结果约等于4:
在这里插入图片描述

从MCV和bucket中评估行数

在这里插入图片描述
在这里插入图片描述
继续举例:id>某个bucket的界限
在这里插入图片描述

在这里插入图片描述
计算单个选择性:
在这里插入图片描述
然后计算最终结果:
在这里插入图片描述

多个列查询条件的选择性相乘评估

在这里插入图片描述

索引扫描

在这里插入图片描述

代价因子的校准

校准参数:seq_page_cost(stap), cpu_tuple_cost(公式)
在这里插入图片描述
用systemtap工具去测试你的内核,下面是测试这个工具能否正常使用。
在这里插入图片描述
准备测试数据:
在这里插入图片描述
查看有多少个页。
在这里插入图片描述
然后关闭数据库
在这里插入图片描述
用root权限将操作系统的缓存清掉 sync; echo 3 > /proc/sys/vm/drop_caches
在这里插入图片描述
重启以非0号cpu去启动数据库,因为0号cpu启动会有额外开销,并查询进程id,用于探测。以非0号cpu启动数据库 taskset -c 1 /opt/module/pgsql9/bin/postgres >/dev/null 2>&1
这个/opt/module/pgsql9/bin是你安装postgresql这个软件的目录。

在这里插入图片描述
然后用root执行监控脚本:

taskset -c 7 stap -e '
global a
probe process("/opt/module/pgsql9/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("/opt/module/pgsql9/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 17986

未完待续!!

auto_explain插件的使用

如果你使用gmake world编译安装,那么就直接登录数据库加载即可,甚至不需要手动extension。我这是用postgres_admin超级用户登的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值