对大表进行分区,但避免长时间锁表

假设您有一个应用程序,该应用程序具有一个巨大的表,并且需要始终可用。它变得如此之大,以至于在不对其进行分区的情况下对其进行管理变得越来越困难。但是,您又不能使表脱机以修改为分区表。

这是处理问题的秘诀。它不一定适用于所有情况,特别是具有非常重的写入负载的表,但它可能适用于许多情况。

首先,让我们设置我们的示例表,并用一些数据填充它,在本例中为 1000 万行:

create table orig_table
( id serial not null,
data float default random()
); create index orig_data_index on orig_table(data);
create index orig_id_index on orig_table(id); insert into orig_table (id)
select nextval('orig_table_id_seq')
from generate_series(1,100000);

现在,我们将设置分区结构。在本例中,我们将在数据字段上使用四个范围:

create table part_table
(like orig_table including defaults including indexes including constraints)
partition by range(data)
(
partition part_1 values LESS THAN (0.25),
partition part_2 values LESS THAN (0.5),
partition part_3 values LESS THAN (0.75),
partition part_table values LESS THAN (maxvalue)
);

我们将重命名原始表,然后使用该名称创建一个视图,该名称是新分区表和旧的非分区表中行的并集,需要一个触发器来处理视图的所有插入、更新和删除操作。然后,我们可以在一个快速事务中转到过渡设置。由于我们不会再向旧的非分区表添加新元组,因此我们禁用了它的AUTOVACUUM。


\set SQLTERM / BEGIN;
/
ALTER TABLE orig_table
RENAME TO old_orig_table;
/ ALTER TABLE old_orig_table
SET (
autovacuum_enabled = false, toast.autovacuum_enabled = false
);
/
CREATE VIEW orig_table AS
SELECT id, data
FROM old_orig_table
UNION ALL
SELECT id, data
FROM part_table
;
/ CREATE or replace TRIGGER orig_table_part_trigger
INSTEAD OF INSERT OR UPDATE OR DELETE
on orig_table
FOR EACH ROW
begin
IF TG_OP = 'INSERT'
THEN
INSERT INTO part_table
VALUES (NEW.id, NEW.data);
RETURN NEW;
ELSIF TG_OP = 'DELETE'
THEN
DELETE
FROM part_table
WHERE id = OLD.id;
DELETE
FROM old_orig_table
WHERE id = OLD.id;
RETURN OLD;
ELSE -- UPDATE
DELETE
FROM old_orig_table
WHERE id = OLD.id;
IF FOUND
THEN
INSERT INTO part_table
VALUES (NEW.id, NEW.data);
ELSE
UPDATE part_table
SET id = NEW.id,
data = NEW.data
WHERE id = OLD.id;
END IF;
RETURN NEW;
END IF;
end;
/
COMMIT;
/ \set SQLTERM ;

请注意,即使正在更新的行来自旧表,所有插入和更新都将定向到分区表。我们将利用这一事实批量移动所有旧行。我们需要的是一个循环程序,它选择少量的旧表行来移动并更新它们,以便移动它们。这是我使用的示例程序 - 它是用Perl编写的,但对于大多数读者来说应该很容易理解,即使不是Perl精通。

--多次执行迁移语句
WITH oldkeys AS
(
SELECT id
FROM old_orig_table
LIMIT 10000
)
UPDATE orig_table
SET id = id
WHERE ID IN (SELECT id FROM oldkeys); select 'orig_table' as tab, count(*) as cnt from orig_table
union all
SELECT 'old_orig_table' as tab, count(*) as cnt FROM old_orig_table
union all
SELECT 'part_table' as tab, count(*) as cnt FROM part_table;
tab | cnt
----------------+--------
orig_table | 100000
old_orig_table | 80000
part_table | 20000
(3 行记录)

如有必要,可以安全地中断此程序。还有其他书写方法。

一旦原始表中不再有数据行,我们就可以用完全分区的表替换视图。在独立的事务中(因为它可能需要一些时间(锁等待),并且并不重要),我们最终删除了旧的非分区表。

BEGIN;
DROP VIEW orig_table CASCADE;
ALTER SEQUENCE orig_table_id_seq OWNED BY part_table.id;
ALTER TABLE part_table RENAME TO orig_table;
COMMIT; BEGIN;
DROP TABLE old_orig_table;
COMMIT;

我们的应用程序应该保持完整的功能,并且没有意识到我们在进行更改。

KingbaseES 普通表在线改为分区表案例的更多相关文章

  1. Oracle在线重定义(online redefinition)--将普通表改为分区表

    使用Oracle的在线重定义技术,可以将Oracle的普通表改为分区表.操作如下: STEP1:测试表是否可以在线重定义,这里以unixdev数据库的LIJIAMAN.BSTEST为例 EXEC DB ...

  2. Oracle大表改为分区表及表空间切换方案

    Oracle大表改为分区表及表空间切换方案 一.            背景 由于之前数据库表和索引放在一个表空间导致表空间数据文件增长太快,文件数量即将达到Oracle表空间的限制,需要对表(没有分 ...

  3. 记一次mysql多表查询(left jion)优化案例

    一次mysql多表查询(left jion)优化案例 在新上线的供需模块中,发现某一个查询按钮点击后,出不来结果,找到该按钮对应sql手动执行,发现需要20-30秒才能出结果,所以服务端程序判断超时, ...

  4. KingbaseES V8R6集群维护案例之---将securecmdd通讯改为ssh案例

    案例说明: 在KingbaseES V8R6的后期版本中,为了解决有的主机之间不允许root用户ssh登录的问题,使用了securecmdd作为集群部署分发和通讯的服务,有生产环境通过漏洞扫描,在88 ...

  5. KingbaseES R3集群在线删除数据节点案例

    案例说明: kingbaseES R3集群一主多从的架构,一般有两个节点是集群的管理节点,所有的节点都可以为数据节点:对于非管理节点的数据节点可以在线删除:但是对于管理节点,无法在线删除,如果删除管理 ...

  6. mysql在线改表结构 pt-online-schema-change

    https://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html 不锁表更改数据库表结构 pt-online-s ...

  7. Mysql大表查询优化技巧总结及案例分析

    http://www.169it.com/article/3219955334.html     sql语句使用基本原则:1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 orde ...

  8. KingbaseES的表空间

    表空间的概念 KingbaseES中的表空间允许在文件系统中定义用来存放表示数据库对象的文件的位置.实际上表空间就是给表指定一个存储目录. 表空间的作用 通过使用表空间,管理员可以控制一个Kingba ...

  9. Hive的内表和外表以及分区表

    1. 内表和外表的区别 内表和外表之间是通过关键字EXTERNAL来区分.删除表时: 内表:在删除时,既删除内表的元数据,也删除内表的数据 外表:删除时,仅仅删除外表的元数据. CREATE [EXT ...

随机推荐

  1. Vue MD5加密你用吗?

    安装 npm install --save js-md5 1.按需引入(在你需要的项目中引入) 引入: import md5 from 'js-md5' 使用: md5('加密信息') 2.全局引入( ...

  2. c# 怎样能写个sql的解析器

    c# 怎样能写个sql的解析器 本示例主要是讲明sql解析的原理,真实的源代码下查看 sql解析器源代码 详细示例DEMO 请查看demo代码 前言 阅读本文需要有一定正则表达式基础 正则表达式基础教 ...

  3. EasyExcel使用

    将下面三层结合起来,请放心食用. 一.controller层 @RestController public class EasyExcelController { private Logger log ...

  4. manjaro 安装后的基本配置

    第一步:设置官方镜像源 sudo pacman-mirrors -i -c China -m rank # 输入以上命令后会有弹出框,选择一个国内镜像(推荐 https://mirrors.ustc. ...

  5. JAVA学习的第一周

    这是发表的第一篇博客,关于Java编程的学习体会如下 1.了解Java的产生与发展时机:1995左右出现Java语言,然后Java的最主要的特点是"跨平台".对于跨平台我不太理解, ...

  6. 【有用的SQL】查Greenplum的数据字典

    Greenplum 查询哪个表的分布键 ( Greenplum ) SELECT att.nspname AS 模式名 , att.relname AS 表名 , table_comment AS 表 ...

  7. k8s配置集ConfigMap详解

    ConfigMap介绍 ConfigMap和Secret是Kubernetes系统上两种特殊类型的存储卷,ConfigMap对象用于为容器中的应用提供配置文件等信息.但是比较敏感的数据,例如密钥.证书 ...

  8. Rust 从入门到精通01-简介

    1.rust 从哪里来 Rust语言在2006年作为 Mozilla 员工 Graydon Hoare 的私人项目出现,而 Mozilla 于 2009 年开始赞助这个项目.第一个有版本号的 Rust ...

  9. 在半小时内从无到有开发并调试一款Chrome扩展(Chrome插件/谷歌浏览器插件)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_120 就在不久之前,我们目前这个毕业班的班长那日同学和我说,他正在公司开发Chrome扩展,看起来很高大上的技术,实际开发却非常简 ...

  10. 【Harmony OS】【ArkUI】ets开发 简易视频播放器

    ​前言:这一次我们来使用ets的Swiper组件.List组件和Video组件制作一个简易的视频播放器.本篇是以HarmonyOS官网的codelab简易视频播放器(eTS)为基础进行编写.本篇最主要 ...