[转帖]金仓数据库KingbaseES V8R6 索引膨胀
索引膨胀
对于索引,随着业务不断的增删改,会造成膨胀,尤其Btree索引,也会涉及索引分裂、合并等,导致索引访问效率降低、维护成本增加。另外,索引页的复用与HEAP PAGE不一样,因为索引的内容是有序结构,只有符合顺序的ITEM才能插入对应的PAGE中,不像HEAP TUPLE,只要有空间就可以插入。index page无论在任何位置,都不能从磁盘删除,因此索引变大后,不能回收空间,除非vacuum full。所以索引膨胀后,通常需要重建索引来回收索引空间。
此外,对于B树索引,新构建的索引比多次更新的索引访问速度稍快,因为逻辑上相邻的页面通常在新构建索引中也是物理上相邻的。为了提高访问速度,定期重新B_Tree 索引可能是值得的。
对于重建索引,REINDEX在任何情况下都可以安全方便地使用。默认情况下,该命令需要ACCESS EXCLUSIVE锁。可以使用CONCURRENTLY选项创建索引,该选项只需要SHARE UPDATE EXCLUSIV锁,不阻塞读写。
索引膨胀的原因:
1.大量删除发生后,导致索引页面稀疏,降低了索引使用效率。
2.长时间运行的事务,阻止了vacuum对表的清理工作,因而导致页面稀疏状态一直保持。
3.索引字段乱序写入,导致索引频繁分裂,使得索引页并不是百分百填满,所以膨胀。
查询获取每个表的行数、索引以及有关这些索引的一些信息:
-
SELECT
-
pg_class.relname,
-
pg_size_pretty(pg_class.reltuples::bigint) AS rows_in_bytes,
-
pg_class.reltuples AS num_rows,
-
COUNT(*) AS total_indexes,
-
COUNT(*) FILTER ( WHERE indisunique) AS unique_indexes,
-
COUNT(*) FILTER ( WHERE indnatts = 1 ) AS single_column_indexes,
-
COUNT(*) FILTER ( WHERE indnatts IS DISTINCT FROM 1 ) AS multi_column_indexes
-
FROM
-
pg_namespace
-
LEFT JOIN pg_class ON pg_namespace.oid = pg_class.relnamespace
-
LEFT JOIN pg_index ON pg_class.oid = pg_index.indrelid
-
WHERE
-
pg_namespace.nspname = 'public' AND
-
pg_class.relkind = 'r'
-
GROUP BY pg_class.relname, pg_class.reltuples
-
ORDER BY pg_class.reltuples DESC;
-
SELECT
-
t.schemaname,
-
t.tablename,
-
c.reltuples::bigint AS num_rows,
-
pg_size_pretty(pg_relation_size(c.oid)) AS table_size,
-
psai.indexrelname AS index_name,
-
pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,
-
CASE WHEN i.indisunique THEN 'Y' ELSE 'N' END AS "unique",
-
psai.idx_scan AS number_of_scans,
-
psai.idx_tup_read AS tuples_read,
-
psai.idx_tup_fetch AS tuples_fetched
-
FROM
-
pg_tables t
-
LEFT JOIN pg_class c ON t.tablename = c.relname
-
LEFT JOIN pg_index i ON c.oid = i.indrelid
-
LEFT JOIN pg_stat_all_indexes psai ON i.indexrelid = psai.indexrelid
-
WHERE
-
t.schemaname NOT IN ('pg_catalog', 'information_schema')
-
ORDER BY 1, 2;
查找重复索引,查找具有相同列集、相同操作类、表达式和谓词的多个索引,但需要人为判断需要删除的重复项:
-
SELECT pg_size_pretty(sum(pg_relation_size(idx))::bigint) as size,
-
(array_agg(idx))[1] as idx1, (array_agg(idx))[2] as idx2,
-
(array_agg(idx))[3] as idx3, (array_agg(idx))[4] as idx4
-
FROM (
-
SELECT indexrelid::regclass as idx, (indrelid::text ||E'\n'|| indclass::text ||E'\n'|| indkey::text ||E'\n'||coalesce(indexprs::text,'')||E'\n' || coalesce(indpred::text,'')) as key
-
FROM pg_index) sub
-
GROUP BY key HAVING count(*)>1
-
ORDER BY sum(pg_relation_size(idx)) DESC;
查找未使用的索引:
-
select
-
indexrelid::regclass as index, relid::regclass as table
-
from
-
pg_stat_user_indexes
-
JOIN pg_index USING (indexrelid)
-
where
-
idx_scan = 0 and indisunique is false;
有些场景,重建索引后,索引就变小了。通常这种情况是索引字段乱序写入,导致索引频繁分裂,使得索引页并不是百分百填满,密度低,索引页面浪费。
索引碎片模拟
-
乱序写入:
-
-
test=# create table t_split(id int);
-
CREATE TABLE
-
test=# create index idx_split on t_split (id);
-
CREATE INDEX
-
test=# insert into t_split select random()*1000000 from generate_series(1,1000000);
-
INSERT 0 1000000
-
test=# \di+ idx_split
-
List of relations
-
Schema | Name | Type | Owner | Table | Size | Description
-
--------+-----------+-------+--------+---------+-------+-------------
-
public | idx_split | index | system | t_split | 30 MB |
-
-
(1 row)
-
-
顺序写入:
-
-
test=# truncate t_split ;
-
TRUNCATE TABLE
-
test=# \di+ idx_split
-
List of relations
-
Schema | Name | Type | Owner | Table | Size | Description
-
--------+-----------+-------+--------+---------+------------+-------------
-
public | idx_split | index | system | t_split | 8192 bytes |
-
-
(1 row)
-
-
test=# insert into t_split select generate_series(1,1000000);
-
INSERT 0 1000000
-
test=# \di+ idx_split
-
List of relations
-
Schema | Name | Type | Owner | Table | Size | Description
-
--------+-----------+-------+--------+---------+-------+-------------
-
public | idx_split | index | system | t_split | 22 MB |
-
-
(1 row)
-
-
先写入数据,后建索引:
-
-
test=# drop index idx_split ;
-
DROP INDEX
-
test=# create index idx_split on t_split (id);
-
CREATE INDEX
-
test=# \di+ idx_split
-
List of relations
-
Schema | Name | Type | Owner | Table | Size | Description
-
--------+-----------+-------+--------+---------+-------+-------------
-
public | idx_split | index | system | t_split | 22 MB |
-
(1 row)
-
-
-
业务运行久了,不断的增删改,也会导致索引碎片:
-
-
test=# create table test(id int);
-
CREATE TABLE
-
test=# insert into test values(generate_series(1,1000000));
-
INSERT 0 1000000
-
test=# create index idx_fragmented on test(id);
-
CREATE INDEX
-
CREATE EXTENSION kbstattuple;
-
刚刚创建的索引没有碎片:
-
test=# \x
-
Expanded display is on.
-
test=# SELECT * FROM pgstatindex('idx_fragmented');
-
-[ RECORD 1 ]------+---------
-
version | 4
-
tree_level | 2
-
index_size | 22609920
-
root_block_no | 289
-
internal_pages | 11
-
leaf_pages | 2748
-
empty_pages | 0
-
deleted_pages | 0
-
avg_leaf_density | 89.93
-
leaf_fragmentation | 0
-
-
-
leaf_fragmentation的碎片率是33.33%:
-
test=# insert into test values(generate_series(1,1000000));
-
INSERT 0 1000000
-
test=# SELECT * FROM pgstatindex('idx_fragmented');
-
-[ RECORD 1 ]------+---------
-
version | 4
-
tree_level | 2
-
index_size | 67846144
-
root_block_no | 289
-
internal_pages | 39
-
leaf_pages | 8242
-
empty_pages | 0
-
deleted_pages | 0
-
avg_leaf_density | 60.06
-
leaf_fragmentation | 33.33
-
-
-
reindex之后,即可回收空间,减少碎片。
-
-
test=# reindex index idx_fragmented;
-
REINDEX
-
test=# \di+ idx_fragmented
-
List of relations
-
-[ RECORD 1 ]---------------
-
Schema | public
-
Name | idx_fragmented
-
Type | index
-
Owner | system
-
Table | test
-
Size | 43 MB
-
Description |
-
-
test=# SELECT * FROM pgstatindex('idx_fragmented');
-
-[ RECORD 1 ]------+---------
-
version | 4
-
tree_level | 2
-
index_size | 45236224
-
root_block_no | 208
-
internal_pages | 26
-
leaf_pages | 5495
-
empty_pages | 0
-
deleted_pages | 0
-
avg_leaf_density | 90.01
-
leaf_fragmentation | 0
总结
通过以上方法监控索引膨胀,以及索引碎片情况,及时对索引reindex 进行碎片优化,建议不要在一个表上建太多索引,准确评估经常update的列和经常select的列,以便创建合适的索引。
[转帖]金仓数据库KingbaseES V8R6 索引膨胀的更多相关文章
- 通过ODBC接口访问人大金仓数据库
国产化软件和国产化芯片的窘境一样,一方面市场已经存在性能优越的同类软件,成本很低,但小众的国产化软件不仅需要高价买入版权,并且软件开发维护成本高:另一方面,国产软件目前普遍难用,性能不稳定,Bug ...
- QT 之 ODBC连接人大金仓数据库
QT 之 使用 ODBC 驱动连接人大金仓数据库 获取数据库驱动和依赖动态库 此操作可在人大金仓官网下载与系统匹配的接口动态库,或者从架构数据库的源码中获取驱动和依赖动态库 分别为: 驱动动态库:kd ...
- 通过jmeter连接人大金仓数据库
某项目用的人大金仓数据库,做性能测试,需要用jmeter来连接数据库处理一批数据.jmeter连接人大金仓,做个记录. 1. 概要 在"配置元件"中添加"JDBC Con ...
- linux安装国产数据库(金仓数据库,达梦数据库,南大通用数据库)
今天在公司做的任务是,在Linux的环境下安装三种数据库,结果一种数据库也没有安装好,首先遇到的问题是安装南大通用数据库遇到安装的第五步,就出现问题了,问题是Gbase SDK没有安装成功,以及Gba ...
- Rocky4.2下安装金仓v7数据库(KingbaseES)
1.准备操作系统 1.1 系统登录界面 1.2 操作系统版本信息 jdbh:~ # uname -ra Linux jdbh -x86_64 # SMP Fri Dec :: CST x86_64 G ...
- 润乾配置连接kingbase(金仓)数据库
问题背景 客户根据项目的不同,使用润乾连接的数据库类型各种各样,此文针对前几日使用润乾设计器连接kingbase金仓数据库做一个说明. kingbase金仓数据库是一款国产数据库,操作方式和配置 ...
- 金仓Kingbase数据库网页数据维护分析工具
金仓Kingbase是优秀的国产数据库产品,在能源,政务,国防等领域广泛使用, 现在TreeSoft数据库管理系统已支持Kingbase了,直接在浏览器中就可以操作查看Kingbase数据了,十分方便 ...
- DBeaver连接达梦|虚谷|人大金仓等国产数据库
前言 工作中有些项目可能会接触到「达梦.虚谷.人大金仓」等国产数据库,但通常这些数据库自带的连接工具使用并不方便,所以这篇文章记录一下 DBeaver 连接国产数据库的通用模版,下文以达梦为例(其他国 ...
- KingbaseES V8R6备份恢复案例之---同一数据库创建不同stanza备份
案例说明: 在生产环境,有的应用需要调用数据库的sys_rman做备份,为了区分数据库自身的sys_rman备份和应用的备份,可以使用不同的stanza name创建备份.本案例介绍了,如何在King ...
- KingbaseES V8R6备份恢复案例之--删除test数据库后sys_backup.sh备份
案例说明: KingbaseES V8R6通过sys_backup.sh执行物理备份,默认sys_backup.sh执行备份初始化时,需要连接test数据库进行身份的认证:在一些生产环境为了安全需求, ...
随机推荐
- 文心一言 VS 讯飞星火 VS chatgpt (144)-- 算法导论12.1 4题
四.用go语言,对于一棵有 n 个结点的树,请设计在 O(n)时间内完成的先序遍历算法和后序遍历算法. 我个人喜欢 灵小智 . 文心一言: 在 Go 语言中,我们可以使用递归来实现树的前序遍历和后序遍 ...
- 最大伪森林——kruskal算法活用 (HDU - 3367)
最大伪森林--kruskal算法活用 (HDU - 3367) kruskal这一用来求生成树的算法,经过修改拓展之后,可以求很多种形式的子图,本题(HDU3367)即为一个应用案例 单击进入原题 以 ...
- maven系列:属性管理和版本管理
目录 一. 属性配置与使用 ①:定义属性 ②:引用属性 二. 资源文件引用属性 ①:定义属性 ②:配置文件中引用属性 ③:开启资源文件目录加载属性的过滤器 ④:配置maven打war包时,忽略web. ...
- 【昇腾】ModelArts与Atlas 200 DK云端协同开发——行人检测Demo(完整版)
摘要:本文主要为大家展示如何基于ModelArts与Atlas 200 DK 端云协同开发的行人检测Demo实现过程. 基于开源数据集,使用ModelArts训练行人检测模型,在本地MindStudi ...
- CANN AICPU算子耗时分析及优化探索
摘要:本文以GreaterEqual作为测试算子,该算子计算逻辑较为简单(output = input1 >= input2),旨在尽可能降低计算耗时,使得算子耗时尽可能以数据操作和算子调度作为 ...
- Solon2 开发之IoC,三、注入或手动获取 Bean
1.如何注入Bean? 先了解一下Bean生命周期的简化版: 运行构建函数 尝试字段注入(有时同步注入,没时订阅注入.不会有相互依赖而卡住的问题) @Init 函数(是在容器初始化完成后才执行) .. ...
- 【eBPF-04】进阶:BCC 框架中 BPF 映射的应用 v2.0——尾调用
这两天有空,继续更新一篇有关 eBPF BCC 框架尾调用的内容. eBPF 技术很新,能够参考的中文资料很少,而对于 BCC 框架而言,优秀的中文介绍和教程更是凤毛麟角.我尝试去网上检索有关尾调用的 ...
- ME51N 创建采购申请
1业务说明 当寻源后,将寻源结果汇总,并创建采购申请,之后据此创建采购订单. 此文档使用BAPI:BAPI_REQUISITION_CREATE创建采购申请 2前台实现 事务代码:ME51N 3代码实 ...
- SuperSocket 简单示例
这是一个SuperSocket 简单示例,包括服务端和客户端. 一.首先使用NuGet安装SuperSocket和SuperSocket.Engine 二.实现IRequestInfo(数据包): 数 ...
- POJ:Dungeon Master(BFS模板题)
原题链接 思路: 正常的思路,只不过是将二维BFS换成三维的,也算是个模板题吧(PS:DFS超容易超时) #include<iostream> #include<queue> ...