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

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

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

首先,让我们设置我们的示例表,并用一些数据填充它,在本例中为 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. js 循环生成元素,并为元素添加click事件,结果只执行最后一个点击事件

    问题描述:有一个参数集合data,for循环为每一个参数生成一个dom元素,并附加onclick事件.生成之后发现点击事件里的参数全是data集合里的最后一个. 代码如下: var dom=$('#d ...

  2. Spring框架系列(5) - 深入浅出SpringMVC请求流程和案例

    前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC:Spring MVC是Spri ...

  3. UiPath屏幕抓取Screen Scraping的介绍和使用

    一.屏幕抓取(Screen Scraping)的介绍 屏幕抓取使您能够在特定的UI元素或文档(如.PDF文档)中提取数据 二.屏幕抓取(Screen Scraping)在UiPath中的使用 [if ...

  4. C# / VB.NET 将Html转为Word

    本文分享以C#程序代码为例,实现将Html文件转换Word文档的方法(附VB.NET代码).在实际转换场景中可参考本文的方法,转换前,请按照如下方法引用Word API的dll文件到Visual St ...

  5. 栈(Stack)和队列

    栈(Stack)和队列 栈是一个后进先出的线性表,它要求只在表尾进行删除和插入操作. 所谓的栈,其实就是一个特殊的线性表.表尾称为栈顶(Top),相应的表头称为栈底(Bottom). 栈的插入(Pus ...

  6. labview从入门到出家8(进阶篇)--简单好用的状态机

    labview的状态机类似于一个软件框架的基本单元,好的软件框架和软件思路采用一个好的状态机,就如虎添翼了.这章给大家讲一个本人常用的一个状态机,基本上以前的项目都是建立在这个状态机上完成的,当然网上 ...

  7. 一文解决Vue中实现 Excel下载到本地以及上传Excel

    相信大家在项目中经常会遇到一些上传下载文件的相关功能,本文就Excel的相关功能进行简述: 咱直接看代码: <div class="import-main-content"& ...

  8. MySQL--SELECT检索语句

    1.检索单个列 SELECT prod_name FROM products; --上述语句利用 SELECT语句从 products表中检索一个名为prod_name的列. 结束SQL:多条SQL语 ...

  9. labview入门到出家11(补充)——基于单片机和labview开发的虚拟示波器

    ​ 之前有小伙伴提到需要虚拟示波器的资料,有些库还有文件丢失了,直接给的工程跑不起来,这里我把关键的地方讲解一下,大家可以自行开发.其实开发不难,只是有些点会耗点时间.虚拟示波器,顾名思义就是非实物的 ...

  10. 可视化查询(sp_helptext)——快速查询包含指定字符串的存储过程(附源码)

    前言 在开发中,随着业务逻辑的调整,修改存储过程是必不可免的. 那怎么定位到需要修改的存储过程呢?一个一个的点开查询?存储过程少的话还行,一旦存储过程过多,这样是很浪费时间的,一个不注意还会遗漏掉. ...