【Y 码力】WAL 与性能

news2024/10/6 20:25:12

【Y 码力】: 是由 YMatrix 研发团队负责的栏目,栏目专注介绍数据库的底层原理、实现细节,以及YMatrix 研发团队不断探索中的工程实践。我们希望栏目能够成为数据库技术的显微镜,同时也能够成为大家了解 YMatrix 研发团队的一扇窗。

摘要

谈到 WAL ,我们总是第一个想到故障恢复,除了能够提供宕机时的数据恢复能力,WAL 其实也被设计用来提高数据库的性能。本文会从基本原理出发,介绍 WAL 是如何提高数据库的性能的。

作者:王任远|YMatrix MXUI 研发工程师

1. WAL 是什么?

WAL 全称是 Write ahead log。顾名思义,WAL 首先是一个日志(log),作为操作日志,记录了数据库中对数据的操作;另外日志的写入发生在数据写入之前,也就是说,任何一个对数据的操作,会由 WAL 首先记录下来,然后数据才会被记录到相应的文件中。

2. WAL 让写入更复杂?

我们先来简单讨论数据写入时的逻辑:

当没有 WAL 的时候,任何写入的的过程可以被朴素的认为只包含 1 步,每次插入/更新都是一个完整的简单操作:

  1. 将更新后的数据直接保存至磁盘

当 WAL 引入后,变成了3步:

  1. 操作日志保存到硬盘
  2. 更新后的数据写入内存(读取时,若一条数据在内存中存在,则会优先读取内存中的数据,而不是硬盘上的内容)
  3. *在恰当的时机(checkpoint) ,将内存中的最新数据存储至磁盘,并清空之前的日志以及内存

该流程仅为演示基本逻辑步骤,在数据库内核的实现中,整个流程的实现要复杂的多。

扩展阅读;

  1. 英文视频介绍:https://www.youtube.com/watch?v=h9n5taRDvfE
  2. The Internals of PostgreSQL:https://www.interdb.jp/pg/pgsql09.html

看起来写入的过程由一步变成三步,变得更加复杂了,可是我们为什么说 WAL 能够提高性能呢?

3. 顺序读写 VS 随机读写

数据库中的数据是会被频繁操作的,因此,我们描述的的写入过程会被频繁的重复,在这个讨论前提下,WAL 能够带来磁盘 IO 操作的优化,从而带来性能的明显提升。

首先关于磁盘的写入过程,我们先有一个基本的认知:

  • 先寻址,再写入

硬盘好比一个作业本,如果我们需要在某一页写入一行内容,那么一共分为两步:

  1. 翻到指定的页
  2. 写入内容

我们考虑两种不同的行为:

A. 如果我们需要在其中的 1, 100,1000页上添加内容,我们执行的过程是:

  1. 翻到对应的页码
  2. 添加1行内容
  3. 重复1、2 三次

B. 如果我们仅需要在最后一页上顺序添加三行,那么我们只需要:

  1. 翻到对应的页码
  2. 添加3行内容

由于对于一个数据库内会存在很多张表,那么当数据库更新表数据时,实际写入的位置,会根据表的不同对应到不同的磁盘位置,行为近似于 A;而写入 WAL 的过程,由于总是按照时间在末尾追加,其行为近似于 B。

A 对应的随机读写,而 B 对应顺序读写。顺序读写明显减少了“翻页”操作,因此从原理上,性能远高于随机读写。

在机械硬盘时代,寻址意味着着磁盘(platter) 的旋转,使磁头(read/write head) 对应到数据所在的准确位置,是一个物理操作,其开销可想而知。而每次读写一个块时,首先就需要通过这些物理操作找到正确位置,然后才能进行进一步的读写,传输工作,因此,顺序读写相比随机读写减少了。

在 SSD 时代,由于机械部件的消失,寻址时不再需要移动磁盘、磁头,这就使得每次读写操作时,“响应速度” 大幅提升,从而大幅提升了随机读写的性能,但从上图的测评我们仍然可以看到,顺序读写的速度仍然明显高于随机读写,当面对密集读写操作时,性能差异就会变得更加“肉眼可见”。

4. 减少随机读写

当没有 WAL 时:

由于数据存储在硬盘不同的位置,可能每写一条,就要重新寻址,开销大。

当引入了 WAL:

  1. 由于 WAL 是日志,根据时间不断追加,因此属于硬盘友好的顺序写入,开销小。
  2. 更新后的数据先写入内存(脏页),以保证数据立即可用,开销很小。

此时一直都没有触发过写磁盘的操作,因此用户可以感知到明显的性能提升。

最后,要保证新数据被持久化,执行。

3. *在恰当的时机存储至磁盘(刷盘),

完成后记录删除这个时间点之前的

WAL 文件以循环利用空间,开销大。

因此,我们只要精细的控制步骤 3,让步骤 3 以较低的频率发生。

  1. 积攒够一批再写,降低执行次数。
  2. 在刷盘过程中,将一批数据合理安排,大多数时候也能明显的降低随机写入,从而提升整体的性能。

思考:

问:数据最终都要落盘,如果内存里存了多个表的不同数据,那么刷盘时还是可以认为是随机写入,那么岂不是性能没有什么变化?

答:如果说我们添加内容的页数分别为 1,10,1,那么写入的时候就可以先写 2 个页码 1 的,再写页码 10 的,这样就减少了一次寻址, 也就是少了一次随机写入,从而提升了性能。

5. 刷盘的最佳策略

如上面所介绍的,刷盘时机的控制策略,会明显影响数据库的性能表现:

  1. 如果刷盘间隔太短,那么就起不到降低硬盘写入操作次数的效果。
  2. 如果刷盘间隔太长,又可能会导致 WAL 积累了太多操作,占用硬盘空间,同时脏页占用大量的内存,执行刷盘时由于要写入的数据量巨大从而导致占用大量硬盘带宽,影响其他操作。

YMatrix 中,刷盘操作的时机,主要由两种机制共同作用。

  1. 周期性触发:检查两次 checkpoint 操作的时间间隔,超过则刷盘。
  2. 阈值触发:发现 WAL 日志的大小达到阈值时,超过则刷盘。

运维思考:

  1. 周期性触发频率由参数 checkpoint_timeout 控制,默认值为 5 分钟。
  2. 阈值触发由参数 max_wal_size 控制,默认值为 4GB。
  3. 数据库进行启动/停止时也会进行刷盘操作。

两种机制结合,就可以保证:

  1. 负载正常时数据被定期被存储至磁盘。
  2. 负载高的数据能及时存储避免 WAL 和脏页积攒过多。

运维参考:

通过命令 CHCEKPOINT 可以立即触发刷盘。

-bash-4.2$
-bash-4.2$ psql postgres
psql (12)
Type "help" for help.

postgres=# CHECKPOINT;
CHECKPOINT

小知识:

  1. WAL 在不同数据库中有不同的名字,在mysql 的 innodb 引擎中被称之为 Redo Log。
  2. WAL 由于完整保存了数据的操作记录,可以用来在多个集群或数据库系统间同步数据,通常 CDC (Change Data Capture) 方案(如 Flink 等)都使用他来同步数据。
  3. 当我们提到 xlog 的时候,指的即是WAL。上古时期,PostgreSQL 一部分地方(比如一些目录,参数和方法)使用了xlog 这个名称,到 PostgreSQL 10时,社区付出了大量努力将命名统一为 WAL。

附录

1. SSD的随机读写和顺序读写:https://www.zhihu.com/question/47544675/answer/2924069738

2. 三星970 PRO 1TB M.2 SSD评测:https://expreview.com/61492-2.html

3. Afraid of SSD? Will SSD kill the profession of database and SQL tuning specialists? https://use-the-index-luke.com/blog/2013-07/afraid-of-ssd

4. Wal and Xlog:https://www.enterprisedb.com/blog/wal-and-xlog

本文为 YMatrix 原创内容,未经允许不得转载。

欲了解更多超融合时序数据库相关信息,请访问 “YMatrix 超融合数据库”

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

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

相关文章

百度千帆大模型文心一言api调用

注册百度智能云账号并申请文心千帆大模型资格 https://login.bce.baidu.com/ https://cloud.baidu.com/product/wenxinworkshop 创建应用获取 创建应用成功后,可以获取到API Key和Secret Key 获取access_token curl https://aip.baidubce.com/oauth/2.0/token?grant_typec…

PyCharm、IDEA、 CLion 专业版安装

1.下载专业版 PyCharm 2.以2023.1.4为例 3.next 4.next 5.next 6.Install 7.Finish 8.Activate 链接:https://pan.baidu.com/s/1N9n8wGgkvjfOX8oDrfX2Hw 提取码:yyds

00_socket_demo

1.服务器端的代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h>#define PORT 8080 #define BUFFER_SIZE 1024int main() {int server_fd, new_soc…

嵌入式Linux基础学习笔记目录

1. 嵌入式Linux应用开发基础知识 1.1 交叉编译 1.2 GCC编译器 1.3 makefire 1.4 文件I/O 1.5 Framebuffer应用编程 1.6 文字显示及图象显示 1.7 输入系统应用编程 1.8 网络编程 1.9 多线程编程 1.10 串口编程 1.11 I2C应用编程 2. 源码分析 2.1 MQTT源码 2.2 蓝牙源码 2.3 MJP…

C# xml序列化以及遇到的坑

需求&#xff1a;需要将对象进行xml序列化&#xff0c;不想包含xml声明也不想格式化 通过百度找到了如下的方法 /// <summary> /// 对象转化为xml字符串 /// </summary> /// <param name"obj"></param> /// <returns></returns>…

uni-app开发小程序时ucharts图表如何使用

在此不会具体告诉大家怎么做&#xff0c;我只告诉大家方法&#xff1a; 第一步&#xff0c;推荐使用组件方法进行绘图&#xff0c;首先去官网下载这个ucharts的插件&#xff1a; 秋云 ucharts echarts 高性能跨全端图表组件 - DCloud 插件市场 下载完毕导入到所需要用到的项目…

学会Spring MVC文件上传、下载和JRebel的使用

目录 引言&#xff1a; 1.文件上传简介 文件上传在Web应用的重要性 2.单文件上传示例 导入依赖 配置文件上传解析器 配置服务器存放文件地址 导入PropertiesUtil工具类 编写resource.properties 添加sql 主页面 文件上传方法 多文件上传示例 文件下载&#xff1a; 文件…

【VAE】

个人网站&#xff1a;https://tianfeng.space 一、VAE 与普通自动编码器一样&#xff0c;变分自动编码器有编码器Encoder与解码器Decoderi两大部分组成&#xff0c;原始图像从编码器输入&#xff0c;经编码器后形成隐式表示(Latent Representation)&#xff0c;之后隐式表示被…

GC 算法与种类

对于垃圾收集&#xff08;GC&#xff09;, 我们需要考虑三件事情&#xff1a;哪些内存需要回收&#xff1f;如何判断是垃圾对象&#xff1f;垃圾回收算法有哪些&#xff1f; 一、GC的工作区域 1、不是GC的工作区域 (1)程序计数器、虚拟机栈和本地方法栈三个区域是线程私有的&…

浅谈UI自动化测试

最近一直在学习python&#xff0c;正好部门技术结构调整&#xff0c;就开始了点工向UI自动化测试的转变&#xff0c;我要说瞌睡来了就掉枕头么&#xff1f; 不过还好&#xff0c;可以将python的学习成果在自动化测试中实践。。。 1、about自动化测试 定义&#xff1a;把人为驱…

SQL5 将查询后的列重新命名

描述 题目&#xff1a;现在你需要查看前2个用户明细设备ID数据&#xff0c;并将列名改为 user_infos_example,&#xff0c;请你从用户信息表取出相应结果。 示例&#xff1a;user_profile iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学…

springboot启动流程梳理

启动顺序主要针对SpringApplication.run&#xff08;&#xff09;方法的梳理 一 SpringApplication类的实例化 ApplicationContextInitializer 实现类的资源配置文件读取以及实现相关类的实例化 1&#xff09;.加载 ApplicationContextInitializer 实现类 &#xff0c;由 Spri…

【数据结构】串

串 串的顺序实现简单的模式匹配算法KMP算法KMP算法的进一步优化 串的顺序实现 初始化 #define MaxSize 50 typedef char ElemType;//顺序存储表示 typedef struct{ElemType data[MaxSize];int length; }SString;/*** 初始化串*/ void InitString(SString *string) {for (int …

【C++】构造函数分类 ③ ( 调用有参构造函数的方法 | 括号法 | 等号法 )

文章目录 一、在不同的内存中创建类的实例对象1、括号法调用构造函数2、等号法调用构造函数 二、完整代码示例 一、在不同的内存中创建类的实例对象 在上一篇博客 【C】构造函数分类 ② ( 在不同的内存中创建类的实例对象 | 栈内存中创建实例对象 | new 关键字创建对象 ) 中 , …

从0到1学会Git(第三部分):Git的远程仓库链接与操作

写在前面:前面两篇文章我们已经学会了git如何在本地进行使用&#xff0c;这篇文章将讲解如何将本地的git仓库和云端的远程仓库链接起来并使用 为什么要使用远程仓库:因为我们需要拷贝我们的代码给别人以及进行协同开发&#xff0c;就需要有一个云端仓库进行代码的存储和同步&a…

nginx配置-gzip

1、想看nginx配置的时候&#xff0c;发现没有nginx命令&#xff0c;是没有配置环境变量。 cd etc/ vim profile 加入 unset i unset -f pathmunge PATH/usr/local/nginx/sbin:$JAVA_HOME/bin:$PATH //这一行 export JAVA_HOME/usr/local/soft/jdk8 expo…

qpushbutton 样式表

QPushButton {color:#ffffff; /*文字颜色*/background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop:0 #aa55ff, stop: 1 #1296db);/*背景色*/border-style:outset; /*边框风格*/border-width:2px;/*边框宽度*/border-color:#0055ff; /*边框颜色*/border-radius:10…

如何用 Java 找到字符串中的元音

这个题目其实不难&#xff0c;这是一个公司面试的时候要求的题目。 这个公司的面试有点意思&#xff0c;他们希望 Zoom 看我的电脑&#xff0c;然后让我解决问题。 题目 题目就非常简单了&#xff0c;他们给了我 2 个字符串。 其中一个是测试字符串&#xff0c;另外一个是元…

I2C 验证中需要注意的问题

I2C验证中需要注意的问题 1.NACK出现的时刻2.Restart和Start区别3.保持时间&#xff08;Thd&#xff09; 1.NACK出现的时刻 通常&#xff0c;在Master访问到错误的Device ID时&#xff0c;Slave会返回Nack&#xff0c;表示访问失败。此外&#xff0c;在Master对Slave读访问时&…

JWT认证、drf-jwt安装和简单使用、实战之使用Django auth的User表自动签发、实战之自定义User表,手动签发

一 JWT认证 在用户注册或登录后&#xff0c;我们想记录用户的登录状态&#xff0c;或者为用户创建身份认证的凭证。 我们不再使用Session认证机制&#xff0c;而使用Json Web Token&#xff08;本质就是token&#xff09;认证机制。Json web token (JWT), 是为了在网络应用环境…