首页 > 数据库 >PostgreSQL在线修改数据类型

PostgreSQL在线修改数据类型

时间:2023-07-12 22:45:32浏览次数:32  
标签:PostgreSQL 在线 temp big 数据类型 id bigint table order

修改大表中列的数据类型几乎总是一件痛苦的事情。由于alter table语句获得的排他锁,它可能会锁定整个表的读写。本文中,我们将探讨如何以最小的影响、最少的锁来执行这样的操作。它适用于任何数据类型;让我们以int到bigint的变化为例。   示范用例 假设我们有一个有许多列的表。其中一列的类型是整型(int,4字节),其值随着时间的推移而递增。一段时间后,我们开始在日志中收到error: integer out of range的信息,这意味着我们试图插入的值大于整数限制(最大值2147483647)。简单的方法是将其类型更改为大整数(bigint,8字节)。下面是我们如何几乎 "在线"完成这一操作的方法。   首先,我们需要创建一个使用新数据类型的列。新创建的列是空列,所以应该在几毫秒内完成。

alter table big_table add column order_id_tmp bigint;
  为了确保没有产生大量的锁,我们可以写个脚本,如果命令执行时间过长,可以将其做超时处理。比如:
cat <<EOF > alter.sql
SET statement_timeout = 100;
ALTER TABLE big_table ADD COLUMN order_id_tmp bigint;
EOF

while true
do
    date
    psql -qX -v ON_ERROR_STOP=1 -f alter.sql && break
    sleep 1
done
statement_timeout将终止运行超过100毫秒的alter table命令,由于psql参数中添加了on_error_stop,其进程将以错误退出。因此,"break"在超时后将不会被执行,因为&&操作符在执行下一个命令前希望第一个命令的退出代码为0,即运行成功。   接下来,我们将创建一个函数和一个触发器,用于将新插入和更新记录中的order_id值复制到order_id_tmp中。
CREATE FUNCTION order_id_bigint() RETURNS TRIGGER AS $BODY$
BEGIN
NEW.order_id_tmp=NEW.order_id;
RETURN NEW;
END
$BODY$ LANGUAGE PLPGSQL;

CREATE TRIGGER order_id_update_or_insert
BEFORE INSERT OR UPDATE ON big_table
FOR EACH ROW EXECUTE PROCEDURE order_id_bigint();
然后我们就可以向新列填充数据了。对于较大的表,我们可以创建一个支持表来帮助完成这一工作。它应该包含主键,在本例中是big_table的列 "ID",用于记录所有新的bigint列为空的记录。
CREATE TABLE public.temp_order_id_bigint(
    id bigint NOT NULL
);
CREATE INDEX id_sorted ON public.temp_order_id_bigint USING btree(id ASC) ;
INSERT INTO public.temp_order_id_bigint
SELECT id FROM big_table
WHERE (order_id IS NOT NULL AND order_id_tmp IS NULL);
  由于MVCC(多版本并发控制)机制和autovacuum的工作原理,Postgres不喜欢大规模更新,因此我们将分块填充数据。更新会一次性更新所有的元组,这将导致巨大的膨胀,表的大小也会增加一倍。
START TRANSACTION;
UPDATE public.big_table
SET
    order_id_tmp = order_id
WHERE id IN (
    SELECT id
    FROM public.temp_order_id_bigint
    ORDER BY id ASC
    LIMIT 5000
);
delete from public.temp_order_id_bigint where id in (
    SELECT id
    FROM public.temp_order_id_bigint
    ORDER BY id ASC
    LIMIT 5000
);
COMMIT;
循环运行上述事务,直到临时表temp_order_id_bigint 为空。   使用最适合你的LIMIT;根据行的大小,你可以使用更低或更高的值来达到更好的效果。在我的测试案例中,5000是最佳值,每5k行在不到300ms的时间内完成。   数据填充完成后,我们就可以执行列切换了。如前所述,我们可以使用与while循环类似的方法。这将确保不会等待锁和阻塞其他会话太长时间。
BEGIN;
LOCK TABLE big_table IN SHARE ROW EXCLUSIVE MODE;
DROP TRIGGER order_id_update_or_insert ON big_table;
ALTER TABLE big_table RENAME COLUMN order_id TO order_id_old;
ALTER TABLE big_table RENAME COLUMN order_id_tmp TO order_id;
COMMIT;
看,将列从int改为bigint,锁定时间不到一秒钟。由于所有的准备工作、数据填充等,该操作本身可能比仅仅更改现有列的数据类型花费更长的时间。但我们避免了使用标准方法所需的停机时间或维护窗口。

标签:PostgreSQL,在线,temp,big,数据类型,id,bigint,table,order
From: https://www.cnblogs.com/abclife/p/17542425.html

相关文章

  • 检测数据类型的四种方法
    一、数据类型:1、基本数据类型:String、Number、Boolean、Null、Undefined、Symbol、BigInt2、引用数据类型:Object、Array、Function、Date、RegExp二、检测数据类型的四种方法1.typeof检测 特点:typeof只能检测基本数据类型(除了null),不能准确的检测引用数据类型。ob......
  • GIS开发:江苏省天地图在线调用地址
    在GIS开发中,使用在线底图地址,除了天地图官网提供的一些开放底图地址,各省的天地图官网也提供了一些开放的底图地址服务,这里分享一下江苏省的几个可用在线底图地址。进入天地图-江苏的资源中心,能够看到一系列共享的影像底图、矢量底图服务,选择就能看到服务的详细信息。资源中心链......
  • PostgreSQL(pg) /MYSQL数据库,使用递归查询(WITH RECURSIVE)功能来实现获取指定菜单ID的
      PostgreSQL/MYSQL数据库,使用递归查询(WITHRECURSIVE)功能来实现获取指定菜单ID的所有下级菜单数据。下方用例是假设菜单表menu的改成自己的表即可WITHRECURSIVEmenu_hierarchyAS(SELECTid,name,parent_idFROMmenuWHEREid=<指......
  • 岩土工程振动在线监测:以道路桥梁基础为例
    岩土工程振动在线监测:以道路桥梁基础为例使用振弦传感器、采集仪和在线监测系统进行岩土工程监测:以道路桥梁基础振动监测为例一个应用振弦传感器、振弦采集仪和在线监测系统构成的岩土工程监测案例是道路桥梁基础的振动监测。 在道路桥梁基础的振动监测方面,振弦传感器可以用......
  • 基本数据类型与引用数据类型
    从内存的角度去解释:基本数据类型:数据值是存储在自己的空间中特点:赋值给其他变量,也是赋的真实的值。引用数据类型:数据值是存储在其他空间中,自己空间中存储的是地址值。特点:赋值给其他变量,赋的地址值。......
  • day11--23.7.11数据类型拓展
    publicclassDemo03{publicstaticvoidmain(String[]args){//整数拓展:进制二进制0b十进制八进制0十六进制0xinti=10;inti2=010;//八进制0inti3=0x10;//十六进制0x0-9A-F16inti4=0x11;Syst......
  • MySQL数据类型(重要)
    整型不同类型存储范围不一样:#默认情况下整型是带负号的tinyint<<<smallint<<<mediumint<<<int<<<biginttinyint:1个字节------>8位------>2^8---->256----->0-255----->-128-127smallint:2个字节存储----->16位---->2^16---->6553......
  • 基于java+springboot的视频点播网站-在线视频点播系统
    该系统是基于java+springboot开发的视频点播系统。是给师妹开发的毕业设计。演示地址前台地址:http://video.gitapp.cn后台地址:http://video.gitapp.cn/admin后台管理帐号:用户名:admin123密码:admin123源码地址https://github.com/geeeeeeeek/java_video功能介绍平台......
  • 基于java+springboot的图书借阅网站-在线图书借阅管理系统
    该系统是基于java+springboot开发的图书借阅管理系统。是给师弟开发的课程作业。大家学习过程中,遇到问题可以github咨询作者。系统演示地址前台http://book.gitapp.cn后台http://book.gitapp.cn/#/admin后台管理帐号:用户名:admin123密码:admin123源码地址https://gith......
  • 针对表的SQL语句、针对记录的SQL语句、存储引擎、数据类型、创建表的完成语法
    针对表的SQL语句有表的前提是先有库什么是表?表相当于文件,表中的一条记录就相当于文件的一行内容,不同的是,表中的一条记录有对应的标题,称为表的字段selectdatabase();查看当前所在库use  库名;使用库1.查看表showtables;查看那所有表showcreatetable t......