PostgreSQL在何处处理 sql查询之二十二
接前面。
回到程序调用关系上来:
estimate_rel_size -> RelationGetNumberOfBlocks->RelationGetNumberOfBlocksINFork
->Smgrnblocks->mdnblocks...
折腾了一圈,就是为了评估一个表的大小。
那么,我们所获得的block,它到底是个什么单位?
BlockNumber mdnblocks(SMgrRelation reln, ForkNumber forknum) {MdfdVec *v = mdopen(reln, forknum, EXTENSION_FAIL);BlockNumber nblocks;BlockNumber segno = 0;/** Skip through any segments that aren't the last one, to avoid redundant* seeks on them. We have previously verified that these segments are* exactly RELSEG_SIZE long, and it's useless to recheck that each time.** NOTE: this assumption could only be wrong if another backend has* truncated the relation. We rely on higher code levels to handle that* scenario by closing and re-opening the md fd, which is handled via* relcache flush. (Since the checkpointer doesn't participate in* relcache flush, it could have segment chain entries for inactive* segments; that's OK because the checkpointer never needs to compute* relation size.)*/while (v->mdfd_chain != NULL){segno++;v = v->mdfd_chain;}for (;;){ nblocks = _mdnblocks(reln, forknum, v);fprintf(stderr,"%d blocks by process %d\n\n",nblocks,getpid());if (nblocks > ((BlockNumber) RELSEG_SIZE))elog(FATAL, "segment too big");if (nblocks < ((BlockNumber) RELSEG_SIZE))return (segno * ((BlockNumber) RELSEG_SIZE)) + nblocks;/** If segment is exactly RELSEG_SIZE, advance to next one.*/segno++;if (v->mdfd_chain == NULL){/** Because we pass O_CREAT, we will create the next segment (with* zero length) immediately, if the last segment is of length* RELSEG_SIZE. While perhaps not strictly necessary, this keeps* the logic simple.*/v->mdfd_chain = _mdfd_openseg(reln, forknum, segno, O_CREAT);if (v->mdfd_chain == NULL)ereport(ERROR,(errcode_for_file_access(),errmsg("could not open file \"%s\": %m",_mdfd_segpath(reln, forknum, segno))));}v = v->mdfd_chain;} }
还是用实验来验证一下吧:
先建立表:
postgres=# create table tst01(id integer); CREATE TABLE postgres=# postgres=# select oid from pg_class where relname='tst01';oid -------16384 (1 row)
据我所知,PostgreSQL中,integer类型的数据会在每条记录中占用4个字节。
那么我想,4字节×2048条记录=8192字节,也就是8K。
事实如何呢?
[root@lex base]# ls ./12788/16384 ./12788/16384postgres=# insert into tst01 values(generate_series(1,2048)); INSERT 0 2048 postgres=# [root@lex base]# ls -lrt ./12788/16384 -rw------- 1 postgres postgres 81920 May 28 11:54 ./12788/16384 [root@lex base]# ls -lrt -kb ./12788/16384 -rw------- 1 postgres postgres 80 May 28 11:54 ./12788/16384 [root@lex base]#
不是8K,而是 80K!
数据量再翻上一倍会如何?
postgres=# insert into tst01 values(generate_series(2049,4096)); INSERT 0 2048 postgres=#[root@lex base]# ls -lrt -kb ./12788/16384 -rw------- 1 postgres postgres 152 May 28 11:56 ./12788/16384 [root@lex base]#
原本我以为,8K为单位的block,仅仅是一小部分是冗余数据(如Header),但事实是并非这样。
问了牛人,得到的答复是:
postgres=# select pg_column_size(id) from tst01 limit 1;pg_column_size ----------------4 (1 row)postgres=# select pg_column_size(t) from tst01 t limit 1;pg_column_size ----------------28 (1 row)
然后再来看程序里对block的处理:
postgres=# select count(*) from tst01;count -------4096 (1 row)postgres=#
此时,后台输出的是:
19 blocks by process 4920
19是什么概念:
[root@lex 12788]# ls -lrt 16384 -rw------- 1 postgres postgres 155648 May 28 11:58 16384 [root@lex 12788]# 155648/8096 = 19.225296442688
正好合拍。所以PostgreSQL的源代码中,mdnblocks 取得的block数目,就是 8K为单位的数据块的个数。
从前面的小实验中也可以看到,如果一条记录中的数据较少,header部分所占冗余就占比较大了。
因此,如果想要正确评估一个表所占用的实际空间,基本上要靠抽样了。
PostgreSQL在何处处理 sql查询之二十二相关推荐
- SQL Server-聚焦深入理解动态SQL查询(三十二)
前言 之前有园友一直关注着我快点出SQL Server性能优化系列,博主我也对性能优化系列也有点小期待,本来打算利用周末写死锁以及避免死锁系列的接着进入SQL Server优化系列,但是在工作中长时间 ...
- FreeSql (二十二)Dto 映射查询
适合喜欢使用 dto 的朋友,很多时候 entity 与 dto 属性名相同,属性数据又不完全一致. 有的人先查回所有字段数据,再使用 AutoMapper 映射. 我们的功能是先映射,再只查询映射好 ...
- 零基础带你学习MySQL—单行子查询和多行子查询(二十二)
零基础带你学习MySQL-多行子查询(二十二) 一.什么是子查询? 子查询是指嵌入在其它 sql 语句中的 select 语句,也叫嵌套查询 二.什么是单行子查询? 单行子查询是指只返回一行数据的子查 ...
- (二十二)查询订单的详情
(二十二)查询订单的详情 案例2-查询订单的详情 需求:只有未付款的订单,点击"付款",跳转到订单的详情页面 步骤分析:1.在订单列表,点击付款,/store/order?meth ...
- 实验二十二 SCVMM中的SQL Server配置文件
实验二十二 SCVMM中的SQL Server配置文件 在VMM 2012中管理员可以使用 SQL Server 配置文件,在部署完成虚拟机之后,实现 SQL Server 数据库服务自动化部署并交付 ...
- Android项目实战(二十二):启动另一个APP or 重启本APP
Android项目实战(二十二):启动另一个APP or 重启本APP 原文:Android项目实战(二十二):启动另一个APP or 重启本APP 一.启动另一个APP 目前公司项目需求,一个主AP ...
- OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()
OpenCV学习(二十二) :反向投影:calcHist(),minMaxLoc(),compareHist() 参考博客: 反向投影backproject的直观理解 opencv 反向投影 颜色直方 ...
- JAVA基础知识总结:一到二十二全部总结
>一: 一.软件开发的常识 1.什么是软件? 一系列按照特定顺序组织起来的计算机数据或者指令 常见的软件: 系统软件:Windows\Mac OS \Linux 应用软件:QQ,一系列的播放器( ...
- Reflex WMS入门系列二十二:物料库存报表
Reflex WMS入门系列二十二:物料库存报表 在Reflex WMS系统上,我们可以通过物料号查询它的HD列表,或者IPG列表.通过在其HD/IPG信息得知其库存数据.当然还可以通过如下方式直接获 ...
- 【转载】 javaweb学习总结(二十二)——基于Servlet+JSP+JavaBean开发模式的用户登录注册 - 孤傲苍狼 - 博 http://www.cnblogs.com/xdp-gacl/
javaweb学习总结(二十二)--基于Servlet+JSP+JavaBean开发模式的用户登录注册 一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+Ja ...
最新文章
- php 下划线转大写开头,使用PHP把下划线分隔命名的字符串 转换成驼峰式命名方式 , 把下划线后面的第一个字母变成大写...
- 中国大学生源质量排行榜150强
- 给你推荐几个 NB 的公众号
- Redis sorted set 类型操作及常用命令
- C语言数字3转变字符 3 程序,大学c语言知识点总结
- 【java基础知识】Spring Boot启动报错com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectExcepti
- [渝粤教育] 西南科技大学 材料力学 在线考试复习资料
- BZOJ_1096_[ZJOI2007]_仓库建设_(斜率优化动态规划+单调队列+特殊的前缀和技巧)
- java课程设计——简易计算器
- Boni Satani谈迁移遗留系统的5个原因
- Exploit开发系列教程-Windows基础shellcode
- 天空卫士API数据安全解决方案
- 优化网站提高打开速度
- EPLAN之设备编号
- WWW 2019 | HAN:异质图注意力网络
- 这次一定 | “学废” 正则表达式
- 8188gu驱动和su realtek_RTL8188CU 和RTL8188SU有什么区别,哪个好,谢谢
- 网易云音乐中你见过最扎心的热评是什么
- 升级windows11的方法
- 乐鑫科技,活跃在国际舞台上的中国芯
热门文章
- 高德地图 JS API - 根据地名实现标记定位
- Linux中查看各文件夹大小(扫盘)
- 1014冒泡排序文法推导
- 数据库三范式的理解(引用其他网友)
- 统计含中英文混编的NSString 字符串长度
- Linux服务器网页显示乱码
- mysql 安全扫描_MySQL 安全和监控 - Can't Wait Any Longer - OSCHINA - 中文开源技术交流社区...
- 【CoppeliaSim】远程 API 之 Matlab 控制,对比 V-rep 有些不同
- 【OFDM频域同步】基于OFDM数字电视地面广播系统中频域同步技术matlab仿真
- 基于FPGA的costas环同步系统仿真与分析