PostgreSQL中HOT对cluster的作用

news2024/11/18 11:39:02

PG中cluster的作用是根据表的索引重新构建一张表,并且表根据该索引进行排序,索引必须提前建好。
注意:cluster操作加ACCESS EXCLUSIVE锁,会阻塞其它任何操作。

我们为什么要运行cluster?

PG中的表是堆表,表中行的顺序可能是乱的,为了加快SQL的查询速度,我们一般会建一个Btree索引,但是如下图所示,可能会造成IO放大,因为要从不同的数据块中取数据,扫描更多的块。
在这里插入图片描述
如何提高范围扫描的效率呢?这里我们就可以考虑使用cluster命令,按索引顺序排列行,这样范围扫描的效率就会高很多,如下,同样扫描三行,只需要扫描一个块。
在这里插入图片描述
显然,一个表只能有一个物理排序,因此只能在表上的一个索引上加速范围扫描。但是,如果两个索引共享前导列,那么将表聚类到其中一个索引上也会在一定程度上加快对另一个索引的范围扫描。

ANALYZE为每列收集的统计数据的时候,列值与行的物理顺序之间也存在相关性。这是一个介于-1和1之间的数。如果相关性为1,则按值的升序排列行。如果相关性为-1,则按值降序对表进行物理排序。在0附近的相关性意味着物理顺序和逻辑顺序之间没有联系。PostgreSQL优化器使用这种相关性来估计索引范围扫描的成本。

cluster的一些缺点

CLUSTER背后的代码与VACUUM (FULL)相同,只是增加了一个排序。因此,CLUSTER存在和VACUUM (FULL)一样的问题:

  • CLUSTER以ACCESS EXCLUSIVE模式锁定表,锁定期间阻塞所有操作
  • 需要二倍于表的空间进行操作

此外,CLUSTER建立的顺序不会持续保持:随后的insert和update不会遵守这个顺序,并且相关性会随着时间的推移而“失效”。因此,如果希望索引范围扫描保持快速,就必须定期对表进行cluster操作。

HOT updates可以保持cluster顺序

DELETE不会破坏行顺序,但是也无法阻止insert打乱相关性。然而,PostgreSQL有一个特性可以防止UPDATE破坏表顺序:HOT更新。
HOT更新将新版本的行放在与旧版本相同的8kB块中,并且它不修改任何索引列,因此它极小干扰索引列的相关性。因此,在HOT更新之后,索引列上的索引范围扫描将保持高效!

如前所述,HOT可以在更新期间保持相关性,但它根本不能帮助INSERT。此外,必须将填充因子设置为低于100才能获得大多数HOT更新,这会人为地使表膨胀。因此,它减慢了顺序扫描并降低了缓存的效率。

下面通过实际例子看下效果:

#创建表,然后设置不同的fillfactor进行测试
CREATE UNLOGGED TABLE clu (
   id  bigint  NOT NULL,
   key integer NOT NULL,
   val integer NOT NULL
) WITH (
   autovacuum_vacuum_cost_delay = 0,
   fillfactor = ???
);

然后尝试不同的填充因子。我将使用pgbench对表进行更新,因此我将autovacuum调整为尽快执行,以便它能够应付工作负载。

插入数据,创建索引,收集统计信息

INSERT INTO clu (id, key, val)
SELECT i, hashint4(i), 0
FROM generate_series(1, 10000000) AS i;

#创建索引
CREATE INDEX clu_idx ON clu(key);
CLUSTER clu USING clu_idx;

#收集统计信息
ALTER TABLE clu ADD PRIMARY KEY (id);
 
/* set hint bits and gather statistics */
VACUUM (ANALYZE) clu;

使用pgbench进行测试

\set i random(1, 10000000)
UPDATE clu SET val = val + 1 WHERE id = :i;

#6个client,更新60 million次
pgbench --random-seed=42 --no-vacuum --file=updates --transactions=10000000 --client=6

然后查看相关性,以及有多少HOT更新,以及autovacuum是否被触发

ANALYZE clu;
SELECT correlation
FROM pg_stats
WHERE tablename = 'clu' AND attname = 'key';


SELECT n_tup_hot_upd, autovacuum_count
FROM pg_stat_user_tables
WHERE relname = 'clu';

只要所有的更新都是HOT,再降低填充系数就没什么不同了。

查看一下表膨胀了多少

SELECT pg_size_pretty(
          pg_table_size('clu')
       ) AS tab_size,
       pg_size_pretty(
          pg_total_relation_size('clu')
          - pg_table_size('clu')
       ) AS ind_size;

在PostgreSQL 15.2中进行不同的fillfactor设置,进行测试后,表和索引膨胀是相对于使用默认填充因子新创建的表和索引的大小来测量的(表占用422 MB,两个索引总共占用428 MB)。
在这里插入图片描述

总结:
如果一个表没有insert操作,那么我们可以设置fillfactor,以便所有或大部分更新都是HOT,那么该表可以在很长的时间内或永远保持在CLUSTER建立的顺序。通过这种方式,我们可以获得快速的索引范围扫描,而不需要或减少定期重新cluster的需要。

参考:
https://www.postgresql.org/docs/current/sql-cluster.html
https://www.cybertec-postgresql.com/en/use-hot-so-cluster-wont-rot-postgresql/
https://dazuiba008.blog.csdn.net/article/details/90749905?spm=1001.2014.3001.5502

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/706933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringMvc接收前端发送的api请求参数问题笔记

SpringMvc接收前端发送的api请求参数问题笔记 get请求参数字符串日期转date接收 需要使用DateTimeFormat注解,来接收前端传的 http://xx.xx.xxx/xsdc?start2023-07-01 15:12:13&end2023-07-02 15:00:00 这种日期参数; 这样获取日期数据就能直接取…

启动一个qemu虚拟机

安装qemu: 编译内核: 编译rootfs; 启动: qemu-system-x86_64 -kernel ./linux-4.14.320/arch/x86_64/boot/bzImage -hda ./busybox-1.36.1/rootfs.img -append "root/dev/sda consolettyS0" -nographic 效果图&am…

乐优购物车微服务过滤拦截器

4.1.2.配置公钥 leyou:jwt:pubKeyPath: D:/heima/rsa/rsa.pub # 公钥地址cookieName: LY_TOKEN # cookie的名称 4.1.3.加载公钥 代码: ConfigurationProperties(prefix "leyou.jwt") public class JwtProperties { ​private String pubKeyPath;// 公…

git远程库GitHub

首先,注册一个GitHub(github.com)帐号,免费获得Git远程仓库 由于本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置: 第1步:创建SSH Key。在用户主目录下&…

学习一波Java语言中的优先队列 PriorityQueue

目录 一、什么是优先队列 二、PriorityQueue 如何使用 三、优先队列的使用场景 一、什么是优先队列 优先队列是一种特殊的队列数据结构,它根据元素的优先级来确定元素的顺序。与普通队列不同的是,优先队列中的元素并不按照插入的先后顺序进行排列&am…

SpringBoot整合logback日志框架详解(提供Gitee源码)

前言:本篇博客主要介绍如何把主流的日志框架快速整合到目前的SpringBoot框架中,对六种日志等级进行介绍以及使用方法。 目录 一、日志级别 1、TRACE 2、DEBUG 3、INFO 4、WARN 5、ERROR 6、FATAL 二、导入pom.xml依赖 三、application.yml配置…

seatunnel-2.3.2 doris数据同步到hive(cdh-6.3.2)首次运行踩坑记录

seatunnel-2.3.2 doris数据同步到hive(cdh-6.3.2)首次运行报错解决,解决的报错如下: 1、java.lang.NoClassDefFoundError: org/apache/hadoop/hive/metastore/api/MetaException 2、java.lang.NoClassDefFoundError: org/apache/thrift/TBase 3、java.la…

arcgis的属性显示bug

arcgis中,右键图层属性可以查看图层的属性信息,比如坐标系、波段数、行列数等。 但是今天实验的时候发现,这个属性中显示的波段最大最小值并非真值。 该图层实际范围为:30~711。 在arcgis属性中,显示范围为0~651。 在…

常用傅里叶变换对 傅里叶变换性质

记录下常用的傅里叶变换对 1. 对称性 2. 尺度变化性 根据上述性质求解: 上述函数可以理解为,cos(wt)的振幅是随着f(t)变化的,这个叫做调幅(幅度受到了调制),不过一般发射的时候,还会发个载波&am…

【SQL应知应会】行列转换(二)• MySQL版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle 行列转换 • Mysql版 前言一、MySQL行列转换1.数据…

SATA 和 ESATA 数据线针脚定义

esata定义 eSATA provides a variant of SATA for external connectivity. It uses a more robust connector, longer shielded cables, and stricter electrical standards. The protocol and logical signaling are identical to internal SATA. eSATA was standardized in 2…

【企业架构框架】SOGAF 通用实体框架 (CoE)

Salesforce 运营、治理和架构框架 (SOGAF) 将 MIT-CISR 企业架构框架应用于 Salesforce 实施和程序。 介绍 为共同实体(即卓越中心)制定一个明确的定义是很棘手的。转换程序中的通用实体 (CoE) 有多种名称: “卓越中心”、“C4E”、“专业中心…

MYSQL-UNION

语法: UNION 操作符用来合并两个 SELECT 语句的结果 SELECT statement UNION [DISTINCT | ALL] SELECT statement UNION 中的 SELECT 语句中的列数、列顺序必须相同 UNION是双目操作符,需要两个SELECT语句作为操作数,UNION后面可以接DISTINCT或者ALL 如果不写DISTINCT或者…

【已解决】Nacos 2.0.2启动异常以及正常启动后账号密码错误问题解决

1.正常解压压缩文件后,在bin目录下直接双击startup.cmd启动Nacos(或bin目录下命令行输入startup.cmd,新版本需要输入startup,cmd -m standalone),发现启动报错。 报错信息我们可以看到大量的sql错误,其中不乏缺少表,jdbc连接异常…

session和token

一、使用HttpSession接口的setAttribute()方法将cookie保存到客户端的浏览器中 二、单点登录逻辑 1、客户端服务有一个过滤器,先判断有没有重定向回来的token值(过去session用,没有也没关系) 2、客户端过滤器再判断session中有没…

使用nodejs操作postgresql

环境准备 1 navicat premium 2 postgresql 14 装完上述软件后,远程连接上之后如下: 自己建立一个用户表users,然后随机生成一些数据即可 步骤 这里我将项目放到了gticode里,可以下载下来使用 https://gitcode.net/wangbiao9292/nodejs-p…

基于物联网、区块链技术的质量管控防伪溯源系统源码

一物一码防伪溯源系统能准确获取产品生产经营各个环节的真实信息,利用物联网、云计算 、区块链、人工智能、5G等先进技术,结合特有的码码关联和RSA加密验证技术,建立区块链的“身份证”,针对产品生长到销售各环节的质量安全数据进…

二、1什么是面向对象编程?

你好,我是程序员雪球,接下来与你一起学习什么是面向对象编程。 面向对象编程是一种编程风格。它以类或对象作为组织代码的基本单元,并将封装,抽象,继承,多态四个特性,作为代码设计的实现基石。 …

Spring Boot 中的 @RabbitListenerContainerFactory 注解

Spring Boot 中的 RabbitListenerContainerFactory 注解 1. 什么是 RabbitListenerContainerFactory 在 Spring Boot 中,我们可以使用 RabbitListener 注解来监听 RabbitMQ 中的消息。RabbitListener 注解会自动创建一个监听器容器,用于接收和处理消息…

Leetcode-每日一题【876.链表的中间结点】

题目 给你单链表的头结点 head ,请你找出并返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。 示例 1: 输入:head [1,2,3,4,5]输出:[3,4,5]解释:链表只有一个中间结点,值为 3…