如何不改变 PostgreSQL 列类型#PG培训

开发应用程序并在其背后操作数据库集群时,会遇到一个意想不到的问题是实践与理论、开发环境与生产之间的差异。这种不匹配的一个完美例子就是更改列类型。
#PG考试#postgresql培训#postgresql考试#postgresql认证
关于如何在 PostgreSQL(以及其他符合 SQL 标准的系统)中更改列类型的常规知识是:

ALTER TABLE table_name
ALTER COLUMN column_name
[SET DATA] TYPE new_data_type

这显然是语义上正确的方式,但是在适当的情况下,您可能会遇到相当不愉快的意外。
在这里插入图片描述

问题

让我们创建一个示例表并演示您可能观察到的孤立行为。让我们从 1000 万行开始(这实际上只是整个数据世界中的一小部分)。

-- create very simple table
CREATE TABLE sample_table (
    id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    label TEXT,
    created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW()
);

-- populate with 10m records
INSERT INTO sample_table (label)
SELECT 
  'hash: ' || md5(random()::text)
FROM generate_series(1, 7000000);

我们将 id 类型从 INT 改为 BIGINT。

alter_type_demo=# ALTER TABLE sample_table ALTER COLUMN id TYPE bigint;
ALTER TABLE
Time: 21592.190 ms (00:21.592)

然后… 21 秒后,您就得到了更改。请注意,这是一个小表,其中大约有 600 MB 的数据。如果您要面对 100 倍于这个数量的情况怎么办?让我们看看幕后发生了什么。

PostgreSQL 必须做的事情

更改数据类型(以及您可能会遇到的许多其他操作)并非易事,PostgreSQL 引擎必须执行多项任务:

  • 重写表是最明显的罪魁祸首。将列从 INT 更改为 BIGINT 需要为每个元组(嗯,想想行)分配 4个额外的字节。由于原始表模式需要固定数量的字节,因此集群以最有效的方式存储它们。也就是说,必须使用正确的元组大小读取和重写每一行(在我们的示例中为1000 万行)。
  • 在我们的综合示例中,锁可能不是问题,但如果您在生产中使用数百或数千个并发查询执行 ALTER 命令,则您必须等待所有查询释放锁。
  • 索引和约束- 如果要更改的列已编入索引或有约束,则需要重建/重新验证它们。这是额外的开销。
  • 事务和预写日志是问题的另一个重要部分。为了保证持久性(ACID 中的“D”),PostgreSQL 必须在 WAL
    文件中记录每个更改。这样,如果数据库崩溃,系统可以重放 WAL 文件以重建自上次检查点以来丢失的修改。

如您所见,执行一些可能被理解为常规表维护的操作涉及很多内容。修改的数据的大小、磁盘 I/O 和容量以及一般系统拥塞都会发挥作用。

但真正的问题并没有就此结束。如果我们谈论的是任何类型的严肃生产部署,你必须考虑更多的事情:

  • 实时复制(包括物理和逻辑复制):这增加了额外的复杂性。对于只读副本,默认行为可确保维护同步提交以实现整个数据库集群的一致性。此设置可保证只有在所有备用副本都确认收到更改后,事务才会完成。然而,这带来了新的挑战,因为性能现在还取决于网络吞吐量(包括潜在的拥塞)以及备用节点的延迟和
    I/O 性能。
  • 恢复和备份是另一个需要考虑的重要领域。虽然常规备份的大小可能不会受到太大影响,但您必须考虑更改前的最后一次备份与下一次备份之间发生的所有事情,并确保时间点一致性。
  • 不太常见但并非闻所未闻的可能是异步副本或逻辑复制的保留槽。生成大量更改(以及 WAL文件)可能会使性能较差(或不频繁)的复制系统落后相当长的时间。虽然这可能是可以接受的,但您需要确保源系统有足够的磁盘空间来保存 WAL文件足够长的时间

如您所见,更改列数据类型并不像看起来那么简单。当前的 CI/CD 实践通常使软件开发人员能够非常轻松地提交数据库迁移并将其推广到生产环境,但几分钟后他们就会发现自己处于生产事件之中。虽然暂存部署可能会有所帮助,但它不能保证与生产具有相同的特征(无论是由于负载水平还是资金限制)。

因此,问题在于(我会重复一遍),修改的数据量的规模、系统的整体拥塞程度、 I/O 容量以及目标表在应用程序设计中的重要性。

归根结底,这转化为完成迁移所需的总时间,以及您的企业可以或可能无法承受的独特限制。解决该问题最简单的方法是将计划维护安排在流量较低的时段并完成它。

如何安全地更改 PostgreSQL 列类型

如果您需要重写数百 GB 甚至 TB 的数据,并且无法承受超过最低限度的停机时间,该怎么办?让我们探索如何正确更改列类型。

让我们先从坏消息开始——你无法避免重写整个表,这将在此过程中生成大量 WAL 文件。这是必然的,你必须计划如何管理它。

好消息:您可以将潜在的停机时间分散到比处理数据所需的更长的时间段。具体要求和限制将根据各个业务需求而有所不同,因此仔细规划至关重要。

完整的迁移可以概括为以下一系列步骤:

  • 向目标表添加具有正确类型的新列。确保该列可以为 NULL 且没有默认值,以避免强制重写整个表1。例如,如果您需要增加ID,则order_id最终会得到新列new_order_id。
  • 设置一个触发器,在有新数据进入时更新新列。这可确保迁移期间的所有新数据都将填充新列。
  • 实现一个函数或逻辑,以便随着时间的推移批量将值从旧列迁移到新列。批次的大小和时间应与您的业务/环境的运营约束相一致。
  • 迁移旧值:根据您的约束、数据大小和 I/O 功能,此过程可能需要数小时到数周甚至更长时间。虽然在终端会话中运行的 SQL 或PL/pgSQL 函数(考虑使用tmux)可能足以完成较短的迁移,但更长的迁移可能需要更复杂的方法。仅此主题就可以成为单独的博客文章或指南的好主题。
  • 迁移完成后,创建反映新列的约束和索引。注意潜在的锁定问题,尤其是当该字段是任何外键的一部分时。

此时,您已准备好执行切换本身。如果您可以验证所有行都已正确填充新列,那么是时候接受最困难的部分了。如果可能的话,在一个事务中或更短的计划停机时间内完成

  • 删除旧列。此操作通常只会短暂锁定表。
  • 删除旧列后,重命名新列。此步骤完成了大部分迁移过程。

考虑重新启动所有依赖于更改的表的应用程序是一种很好的做法,因为某些工具(ORM…我正在看你)可能会缓存 OID 并且不能很好地处理更改。

就是这样 - 但事实并非如此。删除列只会删除引用,数据本身将物理保留在磁盘上。这是您可能需要执行的场景VACUUM FULL- 这可能会锁定表并完全重写它 - 可能会破坏并发迁移的目的。这让我们回到了促使我撰写本指南的原始文章 - [[The Bloat Busters:pg_repack vs pg_squeeze]] 是必经之路。强烈建议提前准备并熟悉这些工具。

结论

虽然更改 PostgreSQL 中的列类型可能像发出 ALTER TABLE 命令一样简单,但对于所有参与其中的人来说,了解与之相关的复杂性非常重要。无论您是请求更改的软件开发人员、审核人员,还是在没有仔细规划的情况下将此类更改部署到生产环境时负责解决事件的个人,深入了解此过程都至关重要。此外,掌握这一特定变化使您能够轻松地将洞察力投射到其他可能代价高昂的操作上。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Hugo Barra对Apple Vision Pro 硬件和软件的详细评述

原文:hugo.blog/2024/03/11/vision-pro 这篇文章的作者是Hugo Barra。Hugo Barra曾是Meta公司(前身为Facebook)旗下Oculus VR/AR团队的负责人。他在2017年至2020年期间领导了Oculus的团队,参与了多个VR头显的开发和发布。Hugo Bar…

MySQL详细介绍:开源关系数据库管理系统的魅力

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……) 2、学会Oracle数据库入门到入土用法(创作中……) 3、手把手教你开发炫酷的vbs脚本制作(完善中……) 4、牛逼哄哄的 IDEA编程利器技巧(编写中……) 5、面经吐血整理的 面试技…

未来20年人工智能将如何塑造社会

照片由Brian McGowan在Unsplash上拍摄 更多资讯,请访问 2img.ai “人工智能会成为我们的救星还是我们的末日?” 几十年来,这个问题一直困扰着哲学家、科学家和科幻爱好者。 当我们踏上技术革命的边缘时,是时候透过水晶球&#x…

从0开始编写VS1053音频解码芯片的底层驱动代码(适用于任何单片机)

VS1053是一个高性能的音频解码器芯片,它是干什么的? 他有两个功能:()用来解码音频文件播放音乐的。(2)将麦克风听到的声音编码成音频文件数据,配合单片机可以保存到SD卡。 单片机加上一个VS1053就可以轻松做一个音乐播放器、一个录音机 等项目。 VS1053支持两种协议:…

Visio文件编辑查看工具:Visio Viewer for Mac 激活版

Visio Viewer 软件通过该软件,用户可以在没有Visio软件的情况下查看使用Visio创建的绘图和图表,方便用户对复杂信息的可视化、分析和交流。Visio Viewer 2007是一个功能强大的软件,它可以帮助IT和商务专业人员轻松地可视化、分析和交流复杂信…

AI论文降重:一键操作,让你的论文查重率瞬间下降

高查重率是许多毕业生的困扰。通常,高查重率源于过度引用未经修改的参考资料和格式错误。传统的降重方法,如修改文本和增添原创内容,虽必要但耗时且成效不一。 鉴于此,应用AI工具进行AIGC降重成为了一个高效的解决方案。这些工具…

PyCharm 2024.1最新变化

PyCharm 2024.1 版本带来了一系列激动人心的新功能和改进,以下是一些主要的更新亮点: Hugging Face 模型和数据集文档预览:在 PyCharm 内部快速获取 Hugging Face 模型或数据集的详细信息,通过鼠标悬停或使用 F1 键打开文档工具窗口来预览。 …

基于springboot、logback的日志脱敏组件

Logback⽇志数据脱敏⼯具:隐私和安全的守护者 概述 在涉及敏感数据的⽇志记录环境中,数据保护和个⼈隐私⽆疑是⾄关重要的领域。确保敏感数据不被泄露,脱敏处理成为必不可少的⼀步。数据脱敏是⼀种技术⼿段,其将敏感信息转换为不…

注意!流量卡的禁区并不一样,请看清楚后再下单!

大家好,我是搜卡之家,今天我又来给大家科普了! 今天科普的内容是关于流量卡禁区! 首先要说一下,流量卡为什么会有禁区?运营商设立禁区主要是为了应对电信诈骗和违法使用电话卡的行为,确保网络…

Studying-代码随想录训练营day21| 669.修建二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树、二叉树总结

第21天,二叉树最后一篇,冲💪 目录 669.修建二叉搜索树 108.将有序数组转换为二叉搜索树 538.把二叉搜索树转换为累加树 二叉树总结 669.修建二叉搜索树 文档讲解:代码随想录修建二叉搜索树 视频讲解:手撕修建二叉…

NAT和内网穿透

NAT(Network Address Translation,网络地址转换)是一种广泛应用于计算机网络的技术,其主要目的是为了解决IPv4地址空间的短缺问题,并且增强网络安全。NAT技术允许一个私有网络内的多个设备共享一个或几个全局唯一的公共…

【Python实战因果推断】2_因果效应异质性2

目录 CATE with Regression Evaluating CATE Predictions CATE with Regression 我想你可能已经预料到了:与应用因果推理中的大多数情况一样,答案往往从线性回归开始。但在走这条路之前,让我们把事情变得更具体一些。假设你在一家遍布全国的…

nuxt3项目打包后获取.env设置的环境变量无效的解决办法

问题描述 在nuxt3项目开发过程中,设置了开发环境变量和生产环境变量,在本地开发时都能正常获取,但打包部署时获取不到,设置如下: //.env.development文件示例 SERVER_API_PATHhttp://192.168.25.100//.env.productio…

Shell (一)Ubuntu的网络配置及软件安装

Ubuntu的配置及软件安装 网络配置 虚拟机提供的网络类型 桥接模式 主机和虚拟机分别拥有不同的ip地址,可以实现和外界设备通信 NAT模式 也可以联网,但是和主机共用同一个ip地址,外界无法识别虚拟机和主机发送的信息 仅主机模式 虚拟机不可…

【Chapter9】设备与IO管理,计算机操作系统教程,第四版,左万利,王英

文章目录 [toc]零、设备管理的功能和目标0.1 设备管理的功能0.2 设备管理的目标 一、设备的分类1.1 输入输出型设备和存储型设备(用途)1.2 独占型设备和共享型设备 二、设备的物理特性2.1 IO设备的物理特性2.2 存储型设备的物理特性2.2.1 磁带的物理特性…

nest.js关键笔记

Nest.js 介绍核心功能设计模式:IOC 控制反转 DI 依赖注入前置知识:装饰器前置知识装饰器-实现一个GET请求 Nestjs脚手架Nestjs cli 常用命令 RESTful 风格设计Nestjs 控制器控制器中常见的参数装饰器 Session 实例Nestjs 提供者工厂模式异步模式 Nestjs …

高中数学:不等式-常用不等式知识点汇总

一、基本性质 比较大小的常用两种方法:作差法,作商法 等式性质 不等式性质 二、基本(均值)不等式 扩展 三、二次函数与一元二次方程不等式 定义 解的对应关系 一元二次不等式的求解过程 四、二元一次不等式(组)与线性规划 关键在于求多个不等…

vite-ts-cesium项目集成mars3d修改相关的包和配置参考

如果vite技术栈下使用原生cesium,请参考下面文件的包和配置修改,想用原生创建的viewer结合我们mars3d的功能的话。 1. package.json文件 "dependencies": {"cesium": "^1.103.0","mars3d": "^3.7.18&quo…

pytorch为自己的extension backend添加profiler功能

pytorch为自己的extension backend添加profiler功能 1.参考文档2.your-extension-for-pytorch需要增加的代码3.pytorch demo及如何调整chrome trace json文件4.[可视化](https://ui.perfetto.dev/) 本文演示了pytorch如何为自己的extension backend添加profiler功能 背景介绍 …

Verilog进行结构描述(二):Verilog基本单元(primitives)

目录 1.Verilog基本单元2.基本单元的引脚 (pin)的可扩展性3.带条件的基本单元4.基本单元实例化 微信公众号获取更多FPGA相关源码: 1.Verilog基本单元 Verilog基本单元提供基本的逻辑功能,也就是说这些逻辑功能是预定义的,用户不需要再定义…