KingbaseESV8R6手工vacuum带有全局分区索引的分区表的影响
背景
客户现场有这样一个案例,有张500个分区的大表,每个分区有20万条记录。有update 非常频繁,经常会触发autovacuum。由于表很大,autovacuum 耗时很长。据现场同事反馈,手工vacuum分区时,有报错:“multiple backends attempting to wait for pincount 1”,大致意思是手工vacuum和autovacuum进程冲突了。经查询sys_stat_activity视图,果然 三个默认的autovacuum进程都在繁忙中。可以查看autovacuum_max_workers参数,默认3,表示autovacuum同时工作的进程数。
面对这样的问题,首先应在应用规划部署前根据业务类型避免这种数据库的架构的存在,比如,拆分业务,或者提前增加参数设置,存储性能等,以避免此风险的发生,目前可以调大autovacuum_max_workers进程数,可是调大这个参数可能造成IO压力过大,这还需要配合监控系统资源使用适度调整该参数。由于需要征得客户同意,目前的方案是关闭autovacuum进程,然后开启手工vacuum分区表。接来下要验证拥有本地分区索引,和全局分区索引的情况下。手工vacuum分区表的影响。
实验环境,关闭autovacuum进程:
测试
验证本地分区索引的分区表,同时vacuum两个分区是否有锁等待,
create table part_tab01(part_key char(1),state char(1),desc_content text)
partition by range(part_key)
(
partition part_0 values less than(1),
partition part_1 values less than(2)
);
insert into part_tab01 select '0','0',repeat('a',1000) from generate_series(1,500000);
insert into part_tab01 select '0','1',repeat('b',1000) from generate_series(1,10);
insert into part_tab01 select '1','1',repeat('a',1000) from generate_series(1,500000);
insert into part_tab01 select '1','0',repeat('b',1000) from generate_series(1,10);
create index idx_part_tab01_state on part_tab01(state);
select count(*) from part_tab01_part_0;
select count(*) from part_tab01_part_1;
alter system set autovacuum=off;
select sys_reload_conf();
show autovacuum;
update part_tab01_part_0 set desc_content='aaa';
update part_tab01_part_1 set desc_content='bbb';
检查分区膨胀率
SELECT
schemaname||'.'||relname,
n_dead_tup,
n_live_tup,
round(n_dead_tup * 100 / (n_live_tup + n_dead_tup),2) AS dead_tup_ratio
FROM
pg_stat_all_tables
WHERE relname='part_tab01_part_0'
ORDER BY dead_tup_ratio DESC;
?column? | n_dead_tup | n_live_tup | dead_tup_ratio
--------------------------+------------+------------+----------------
public.part_tab01_part_0 | 100010 | 100010 | 50.00
(1 row)
SELECT
schemaname||'.'||relname,
n_dead_tup,
n_live_tup,
round(n_dead_tup * 100 / (n_live_tup + n_dead_tup),2) AS dead_tup_ratio
FROM
pg_stat_all_tables
WHERE relname='part_tab01_part_1'
ORDER BY dead_tup_ratio DESC;
?column? | n_dead_tup | n_live_tup | dead_tup_ratio
--------------------------+------------+------------+----------------
public.part_tab01_part_1 | 100010 | 100010 | 50.00
(1 row)
分别在两个窗口同时执行如下vacuum命令
vacuum part_tab01_part_0;
vacuum part_tab01_part_1;
没有锁等待,可以同时完成两个分区的vacuum
验证全局分区索引的分区表,同时vacuum两个分区是否有锁等待
create table t1_part(id1 integer,id2 integer,id3 integer)
partition by range(id2)
(
partition part01 values less than(10000),
partition part02 values less than(20000),
partition part03 values less than(30000),
partition part04 values less than(40000),
partition part05 values less than(50000),
partition part06 values less than(60000),
partition part07 values less than(70000),
partition part08 values less than(80000),
partition part09 values less than(90000),
partition part10 values less than(maxvalue)
);
create unique index idx2_t1_part on t1_part(id2) global ;
create index idx3_t1_part on t1_part(id2) ;
查看索引
TEST=# \di+ idx2_t1_part
List of relations
Schema | Name | Type | Owner | Table | Size | Description
--------+--------------+--------------+--------+---------+------------+-------------
public | idx2_t1_part | global index | system | t1_part | 8192 bytes |
(1 row)
TEST=# \di+ idx3_t1_part;
List of relations
Schema | Name | Type | Owner | Table | Size | Description
--------+--------------+-------------------+--------+---------+---------+-------------
public | idx3_t1_part | partitioned index | system | t1_part | 0 bytes |
(1 row)
insert into t1_part select generate_series(1,100000),generate_series(1,100000),generate_series(1,100000);
update t1_part set id3='443';
用下面语句查询每个分区膨胀率早已经超过了autovacuum阈值,由于分区众多,结果略过
SELECT
schemaname||'.'||relname,
n_dead_tup,
n_live_tup,
round(n_dead_tup * 100 / (n_live_tup + n_dead_tup),2) AS dead_tup_ratio
FROM
pg_stat_all_tables
WHERE relname ='t1_part_part01'
ORDER BY dead_tup_ratio DESC;
分别在多个窗口同时执行如下vacuum命令
vacuum t1_part_part01
vacuum t1_part_part02
vacuum t1_part_part03
果然并发执行子分区时,全局分区索引报错,不允许并发vacuum子分区,原因是当vacuum分区表时,同时包含了vacuum index操作,vacuum多个分区表同时,对同一个全局分区索引vacuum引起的等待。
TEST=# vacuum t1_part_part02
TEST-# ;
ERROR: multiple active vacuums for index "idx2_t1_part"
这时,只能vacuum主分区表可以成功
TEST=# vacuum t1_part;
VACUUM
分别查看各分区表的膨胀率已经降到了0,由于分区众多,这里只列举了两个分区
TEST=# SELECT
TEST-# schemaname||'.'||relname,
TEST-# n_dead_tup,
TEST-# n_live_tup,
TEST-# round(n_dead_tup * 100 / (n_live_tup + n_dead_tup),2) AS dead_tup_ratio
TEST-# FROM
TEST-# pg_stat_all_tables
TEST-# WHERE relname ='t1_part_part05'
TEST-# ORDER BY dead_tup_ratio DESC;
?column? | n_dead_tup | n_live_tup | dead_tup_ratio
-----------------------+------------+------------+----------------
public.t1_part_part05 | 0 | 10000 | 0.00
(1 row)
TEST=# SELECT
TEST-# schemaname||'.'||relname,
TEST-# n_dead_tup,
TEST-# n_live_tup,
TEST-# round(n_dead_tup * 100 / (n_live_tup + n_dead_tup),2) AS dead_tup_ratio
TEST-# FROM
TEST-# pg_stat_all_tables
TEST-# WHERE relname ='t1_part_part06'
TEST-# ORDER BY dead_tup_ratio DESC;
?column? | n_dead_tup | n_live_tup | dead_tup_ratio
-----------------------+------------+------------+----------------
public.t1_part_part06 | 0 | 10000 | 0.00
(1 row)
总结
- 在对表进行Vacuum时,需要获取ShareUpdateExclusiveLock锁,而同一张表两个ShareUpdateExclusiveLock锁是冲突的,不允许两个进程vacuum 同一张表。
- 对于分区表父表vacuum,实际是对分区子表进行vacuum
对于有全局分区索引的分区表,在手工vacuum表时,首先vacuum主表,然后需要用到 INDEX_CLEANUP特性,vacuum (verbose, INDEX_CLEANUP false) t1_part;尤其适用于本案例,有全局分区索引时,表和索引膨胀率很高时,建议在vacuum 表时,跳过索引,最后vacuum表后,重建索引。
这部分内容请参考博客园文档《KingbaseES V8R6 vacuum index_cleanup 选项》
https://www.cnblogs.com/kingbase/p/16145397.html
KingbaseESV8R6手工vacuum带有全局分区索引的分区表的影响的更多相关文章
- Oracle非分区索引,全局分区索引和本地分区索引。
1.如果按照索引是否分区作为划分依据,Oracle 的索引类型可以分为非分区索引,全局分区索引和本地分区索引. 2.创建演示实例 --创建非分区表create table test_partition ...
- 记一次全局分区索引update调优
原始SQL: CREATE OR REPLACE PROCEDURE sp_upd_suppressed_emails( A_LIMIT_BULK IN PLS_INTEGER DEFAULT 20 ...
- Postgresql 全局索引与分区索引对于SQL性能影响的比较及DDL操作后分区全局索引是否会失效
Postgresql 提供了对于分区表 global index 的支持.global index 不仅提供了对于唯一索引功能的改进(无需包含分区键),而且在性能上相比非global index (l ...
- 全局索引与分区索引对于SQL性能影响的比较
KingbaseES 提供了对于分区表 global index 的支持.global index 不仅提供了对于唯一索引功能的改进(无需包含分区键),而且在性能上相比非global index (l ...
- Atitit.分区对索引的影响 分区索引和全局索引 attilax总结
Atitit.分区对索引的影响 分区索引和全局索引 attilax总结 1. 分区的好处1 2. 分区键:2 3. 分区的建议:2 4. 分区索引和全局索引:2 5. 全局索引就是在全表上创建索引, ...
- Oracle分区索引
索引与表类似,也可以分区: 分区索引分为两类: Locally partitioned index(局部分区索引) Globally partitioned index(全局分区索引) 下面就来详细解 ...
- PLSQL_Oracle分区表和相应的分区索引管理和使用(案例)
2014-08-22 Created By BaoXinjian
- 01 Oracle分区索引
Oracle分区索引 索引与表类似,也可以分区: 分区索引分为两类: Locally partitioned index(局部分区索引) Globally partitioned index(全局 ...
- [Oracle]分区索引
上一节学习了分区表,接着学习分区索引. (一)什么时候对索引进行分区 · 为了避免移动数据时重建整个索引,可对索引分区,在重建索引时,只需重建与数据分区相关的索引: · 在对分区表进行维护时,为了避免 ...
- oracle分区表和分区索引概述
㈠ 分区表技术概述 ⑴ Range 分区 ① 例子 create table t (...列定义...) ...
随机推荐
- 【Unity3D】同步Socket通讯
1 前言 在多人对战网络游戏中,玩家之间一般不是直接通讯,而是与服务器通讯,服务器再把消息转发给其他玩家.网络通讯一般基于 Socket 实现,也有一些开源网络游戏框架,如:光子引擎 Photon ...
- Oracle SQL 注入攻击
All about Security - SQL Injection 最近做个一个有关ORACLE数据库安全的网上研讨.我们有1300多位参与者,反馈相当丰富. I recently did a we ...
- centos7源码方式安装zabbix-4.0
1.关闭防火墙 systemctl stop firewalld.service #临时关闭firewall systemctl disable firewalld.service #禁止firewa ...
- 【Azure Redis 缓存】如何使得Azure Redis可以仅从内网访问? Config 及 Timeout参数配置
问题描述 问题一:Redis服务,如何可以做到仅允许特定的子网内的服务器进行访问? 问题二:Redis服务,timeout和keepalive的设置是怎样的?是否可以配置成timeout 0? 问题三 ...
- 了解 Docker 网络
本章将会简单地讲述 Docker 中的网络,对于 CNM.Libnetwork 这些,限于笔者个人水平,将不会包含在内. Docker 的四种网络模式 Docker 有 bridge.none.hos ...
- ASP.NET Core 从入门到精通-资源收集导航
ASP.NET Core 从入门到精通-资源收集导航 目录 ASP.NET Core 从入门到精通-资源收集导航 学习路线 学习路线资源导航大全 1,介绍 2,入门 3,教程 创建 Razor 页面 ...
- 读 NebulaGraph源码 | 查询语句 LOOKUP 的一生
本文由社区用户 Milittle 供稿 LOOKUP 是图数据库 NebulaGraph 的一个查询语句.它依赖索引,可以查询点或者边的信息.在本文,我将着重从源码的角度解析一下 LOOKUP 语句的 ...
- mysql-对应删除 dict 脚本
-- 1. 此 dict 是在不同租户下的数据字典,查询时需要根据 departid 进行分类查询 -- 2. 删除dict, dict分类主表类型与挂载的子表数据 -- 3. 通过查询到的主表的 g ...
- 【简历模板】极简Markdown程序员简历模板
前言 最近在找工作,一份好的简历是敲门砖,所以跟大家分享下简洁明了大方MarkDown的简历模板和在线编辑工具 在线工具 冷熊 Java工程师简历模板 下载 点击下载 预览 个人信息 xxx/男/19 ...
- Java 练习题(类+调用方法)
1 /* 2 * 3 * 定义一个 PassObject,在类中定义一个方法printAress(),该方法的定义如下: 4 * public void printAreas(Circle c,int ...