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 (...列定义...) ...
随机推荐
- haproxy ssl证书配置
通常情况下,web应用程序的ssl证书放置于nginx的服务器,但很多时候前面会加一次负载均衡,使用HAProxy可以实现https的证书安全,从客户浏览器到HAProxy代理服务器之间为ssl加密传 ...
- 如何获取oracle dbid
1.查询v$database获得 由于DBID在控制文件和数据文件中都存在记录,所以如果能够mount数据库就可以查询v$database视图获得. SQL> alter database m ...
- python课本学习-第五章
一.列表的概念 1.列表的创建 列表是由一组任意类型的值组合而成的序列,组成列表的值称为元素,每个元素之间用逗号隔开. 列表中的元素是可变的 #列表类似于c++中的数组,数组下标从0开始 list1 ...
- 文心一言 VS 讯飞星火 VS chatgpt (200)-- 算法导论15.2 4题
四.用go语言,对输入链长度为 n 的矩阵链乘法问题,描述其子问题图:它包含多少个顶点?包含多少条边?这些边分别连接哪些顶点? 文心一言: 矩阵链乘法问题是一个经典的动态规划问题,其中给定一个矩阵链, ...
- C++ GDAL用CreateCopy()新建栅格并修改波段的个数
本文介绍基于C++语言GDAL库,为CreateCopy()函数创建的栅格图像添加更多波段的方法. 在C++语言的GDAL库中,我们可以基于CreateCopy()函数与Create()函数创 ...
- django学习第三天---django模板渲染,过滤器,反向循环 reversed,自定义标签和过滤器,模板继承
django模板渲染 模板渲染,模板指的就是html文件,渲染指的就是字符串替换,将模板中的特殊符号替换成相关数据 基本语法 {{ 变量 }} {% 逻辑 %} 变量使用 示例 Views.py文件 ...
- fastdfs存储和下载过程
- 【LeetCode链表#11】环形链表II(双指针)
环形链表II 力扣题目链接(opens new window) 题意: 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,使用整数 pos 来表示 ...
- [golang] 概念: struct vs interface
struct vs interface go语言的简化哲学: class = struct + receiver method set 注意: go 语言的struct,在参数传递中,是值拷贝. st ...
- 当 GraphQL 遇上图数据库,便有了更方便查询数据的方式
人之初,性本鸽. 大家好,我叫储惠龙(实名上网),你可以叫我小龙人,00 后一枚.目前从事后端开发工作. 今天给大家带来一个简单的为 NebulaGraph 提供 GraphQL 查询支持的 DEMO ...