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 (...列定义...) ...
随机推荐
- 使用sqlmap执行SQL注入并获取数据库用户名
Sqlmap介绍 sqlmap支持MySQL, Oracle,PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, ...
- ubuntu 23.04 无法联网
一些参考文章: 解决ubuntu突然无法联网问题 共享主机网络方法: https://www.server-world.info/en/note?os=Ubuntu_22.04&p=squid ...
- C++ 虚基类
虚基类(Virtual Base Class)在面向对象编程中的作用是解决多重继承中的菱形继承问题(Diamond Inheritance Problem)和共享基类问题(Shared Base Cl ...
- win32 - 创建带有标准阴影的无边框窗口
这个框框好像删不掉,就先放这边吧... #define WIN32_LEAN_AND_MEAN #include <unknwn.h> #include <windows.h&g ...
- 【Android逆向】frida hook so 函数
1. apk来自52pojie 链接:https://pan.baidu.com/s/1vKC1SevvHfeI7f0d2c6IqQ 密码:u1an 2.apktool反编译apk,拿到so文件 ja ...
- 自定义组件WebComponents加HTML模板template元素及shadowDOM影子DOM及定义一些事件
自定义组件WebComponents加HTML模板template元素及shadowDOM影子DOM及定义一些事件 Web Components 自定义组件,可以自定义一个类似于div的元素,里面的事 ...
- xcode真机运行包添加(更新到15.4)
今天给真机装包,提示xcode版本低不能安装,电脑内存有些不足,xcode更新不了,这时候了解到xcode可以单独添加开发包\(^o^)/~ 1.下载 链接: https://pan.baidu.co ...
- django学习第十三天--自定义中间件
jquery操作cookie 下载地址 http://plugins.jquery.com/cookie/ 引入 <script type="text/javascript" ...
- Alpine安装gcc g++ make编译环境
apk add gcc g++ make cmake gfortran libffi-dev openssl-dev libtool
- APScheduler可能遇到的问题
uWsgi使用多进程模式启动Django项目,因此我们会有多个进程去执行这个定时任务,导致定时任务被重复执行.解决这个问题的方法,我们直接就会想到采用加锁的方式.第一个拿到锁的进程,执行定时任务,其余 ...