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

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

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

首先,让我们设置我们的示例表,并用一些数据填充它,在本例中为 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. 【RocketMQ】消息的存储

    Broker对消息的处理 BrokerController初始化的过程中,调用registerProcessor方法注册了处理器,在注册处理器的代码中可以看到创建了处理消息发送的处理器对象SendMe ...

  2. SELECT 的6大子句

    SELECT 6大子句的顺序: SELECT selection_list /*要查询的列名称*/, 结果的字段列表 FROM table_list /*要查询的表名称*/, 后面跟表,视图,多行多列 ...

  3. 构建 API 的7个建议【翻译】

    迄今为止,越来越多的企业依靠API来为客户提供服务,以确保竞争的优势和业务可见性.出现这个情况的原因是微服务和无服务器架构正变得越来越普遍,API作为其中的关键节点,继承和承载了更多业务. 在这个前提 ...

  4. 破坏正方形UVA1603

    题目大意 有一个由火柴棍组成的边长为n的正方形网格,每条边有n根火柴,共2n(n+1)根火柴.从上至下,从左到右给每个火柴编号,现在拿走一些火柴,问在剩下的后拆当中ongoing,至少还要拿走多少根火 ...

  5. 关于 CMS 垃圾回收器,你真的懂了吗?

    大家好,我是树哥. 前段时间有个小伙伴去面试,被问到了 CMS 垃圾回收器的详细内容,没答出来.实际上,CMS 垃圾回收器是回收器历史上很重要的一个节点,其开启了 GC 回收器关注 GC 停顿时间的历 ...

  6. Redis系列4:高可用之Sentinel(哨兵模式)

    Redis系列1:深刻理解高性能Redis的本质 Redis系列2:数据持久化提高可用性 Redis系列3:高可用之主从架构 1 背景 从第三篇 Redis系列3:高可用之主从架构 ,我们知道,为Re ...

  7. BACnet IP转OPC UA网关

    BACnet是楼宇自动化和控制网络数据通信协议的缩写.它是为楼宇自动化网络开发的数据通信协议   根据1999年底互联网上楼宇自动化网络的信息,全球已有数百家国际知名制造商支持BACnet,包括楼宇自 ...

  8. mysql 之full join

    首先,mysql中是不支持full join的,如果要实现类似的功能可以用union all,union会剔除重复.以下是实现实例 create table if not exists t1(`id` ...

  9. Docker 好用的镜像

    Docker 官方镜像 1.个人博客空间wordpress 2.开源管理系统odoo 3.开发文档生成工具star7th/showdoc.(启动说明文档https://www.showdoc.com. ...

  10. 羽夏看Linux内核——段相关入门知识

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作.如想转载,请把我的转载信息附在文章后面,并 ...