Postgresql 自动真空后的索引大小
你好。我正在阅读博士后关于真空处理和重新索引程序的官方文件。有些句子对我来说不清楚,所以我想澄清一下。第12版Postgres文档 首先。我知道autovacuum会检查表中的死元组,将它们的位置存储在名为maintenance_work_mem的特殊内存中,然后在内存已满时,真空删除所有索引中引用这些位置的对应页面。关于reindex的文档 完全为空的B树索引页将被回收用于 重复使用。然而,仍有可能存在使用效率低下的问题 空格:如果一个页面上除了几个索引键以外的所有索引键都已删除,则 页面仍被分配Postgresql 自动真空后的索引大小,postgresql,reindex,vacuum,Postgresql,Reindex,Vacuum,你好。我正在阅读博士后关于真空处理和重新索引程序的官方文件。有些句子对我来说不清楚,所以我想澄清一下。第12版Postgres文档 首先。我知道autovacuum会检查表中的死元组,将它们的位置存储在名为maintenance_work_mem的特殊内存中,然后在内存已满时,真空删除所有索引中引用这些位置的对应页面。关于reindex的文档 完全为空的B树索引页将被回收用于 重复使用。然而,仍有可能存在使用效率低下的问题 空格:如果一个页面上除了几个索引键以外的所有索引键都已删除,则 页面仍被
问题是。如果页面保持已分配状态,是否意味着autovacuum不会将索引中已删除页面的物理空间返回操作系统?例如,索引占用1GB内存。我从表中删除了除一行以外的所有行,然后运行真空吸尘器。在这种情况下,索引仍将占用1GB内存。我说得对吗?真空是,真空满时否:
select version();
version
---------------------------------------------------------------------------------------------------------
PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)
create table t(s text);
CREATE TABLE
insert into t select generate_series(1,300000)::text;
INSERT 0 300000
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
create index on t(s);
CREATE INDEX
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
delete from t where s <> '1';
DELETE 299999
select count(*) from t;
count
-------
1
(1 row)
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
vacuum t;
VACUUM
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
48 kB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
vacuum full t;
VACUUM
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
16 kB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
16 kB
(1 row)
REINDEX没有:
select version();
version
---------------------------------------------------------------------------------------------------------
PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)
create table t(s text);
CREATE TABLE
insert into t select generate_series(1,300000)::text;
INSERT 0 300000
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
create index on t(s);
CREATE INDEX
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
delete from t where s <> '1';
DELETE 299999
select count(*) from t;
count
-------
1
(1 row)
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
reindex table t;
REINDEX
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
16 kB
(1 row)
真空时为是,真空满时为否:
select version();
version
---------------------------------------------------------------------------------------------------------
PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)
create table t(s text);
CREATE TABLE
insert into t select generate_series(1,300000)::text;
INSERT 0 300000
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
create index on t(s);
CREATE INDEX
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
delete from t where s <> '1';
DELETE 299999
select count(*) from t;
count
-------
1
(1 row)
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
vacuum t;
VACUUM
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
48 kB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
vacuum full t;
VACUUM
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
16 kB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
16 kB
(1 row)
REINDEX没有:
select version();
version
---------------------------------------------------------------------------------------------------------
PostgreSQL 12.3 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit
(1 row)
create table t(s text);
CREATE TABLE
insert into t select generate_series(1,300000)::text;
INSERT 0 300000
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
create index on t(s);
CREATE INDEX
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
delete from t where s <> '1';
DELETE 299999
select count(*) from t;
count
-------
1
(1 row)
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
6600 kB
(1 row)
reindex table t;
REINDEX
select pg_size_pretty(pg_table_size('t'));
pg_size_pretty
----------------
10 MB
(1 row)
select pg_size_pretty(pg_indexes_size('t'));
pg_size_pretty
----------------
16 kB
(1 row)
src/backend/access/nbtree中的自述文件对此有很多深入的信息。这个答案中的引语来自那里
如果确实删除了表中除一行以外的所有行,则索引中的几乎所有页面都将被删除
<>我们考虑只从BTALL中删除整个页面,直到它变成
完全没有物品。合并部分完整的页面将允许更好的
空间重用,但将现有数据项向左或向右移动似乎不切实际
这样做是正确的——扫描方向相反
如果是这样,可能会错过这些项目。而且,我们从不删除最右边的页面
在树级别上,此限制简化了遍历算法,如下所示:
解释如下。页面删除总是从空页开始。一
内部页面只能作为删除整个子树的一部分删除。
这始终是一个由内部页面链组成的瘦子树
加上一页。子树的每一层上都有一页,
并且每个级别/页面覆盖相同的键空间
空间不会释放到操作系统,但是:
回收页面实际上并不会改变它在磁盘上的状态,我们只是简单地说
将其记录在共享内存可用空间映射中,并从中删除
下一次拆分页面需要新页面时分发
树将变得“瘦”,因为索引的深度永远不会缩小。PostgreSQL对此进行了优化:
因为我们从不删除任何级别最右边的页面,尤其是
永远不要删除根,树的高度是不可能删除的
减少在大量删除之后,我们可能会出现这样一种情况:
树很瘦,根下面有几个单页级别。
在这种情况下,操作仍然是正确的,但我们会浪费周期
在单页级别中递减。为了解决这个问题,我们使用了一个想法
来自Lanin和Shasha:我们跟踪快速根级别,即
最低的单页级别。元数据页面保留指向此的指针
级别以及真正的根。所有普通操作都会启动它们的
在快速根处搜索,而不是在真实根处搜索
如果在索引上运行REINDEX INDEX或清空整个表,索引将被重建,空间将被释放。src/backend/access/nbtree中的自述文件有很多关于这方面的深入信息。这个答案中的引语来自那里
如果确实删除了表中除一行以外的所有行,则索引中的几乎所有页面都将被删除
<>我们考虑只从BTALL中删除整个页面,直到它变成
完全没有物品。合并部分完整的页面将允许更好的
空间重用,但将现有数据项向左或向右移动似乎不切实际
这样做是正确的——扫描方向相反
如果是这样,可能会错过这些项目。而且,我们从不删除最右边的页面
在树级别上,此限制简化了遍历算法,如下所示:
解释如下。页面删除总是从空页开始。一
内部页面只能作为删除整个子树的一部分删除。
这始终是一个由内部页面链组成的瘦子树
加上一页。子树的每一层上都有一页,
并且每个级别/页面覆盖相同的键空间
空间不会释放到操作系统,但是:
回收页面实际上并不会改变它在磁盘上的状态,我们只是简单地说
将其记录在共享内存可用空间映射中,并从中删除
下一次拆分页面需要新页面时分发
树将变得“瘦”,因为索引的深度永远不会缩小。PostgreSQL对此进行了优化:
因为我们从不删除任何级别最右边的页面,尤其是
永远不要删除根,它是impo
这棵树的高度可以
减少在大量删除之后,我们可能会出现这样一种情况:
树很瘦,根下面有几个单页级别。
在这种情况下,操作仍然是正确的,但我们会浪费周期
在单页级别中递减。为了解决这个问题,我们使用了一个想法
来自Lanin和Shasha:我们跟踪快速根级别,即
最低的单页级别。元数据页面保留指向此的指针
级别以及真正的根。所有普通操作都会启动它们的
在快速根处搜索,而不是在真实根处搜索
如果在索引上运行REINDEX INDEX或清空表,索引将被重建,空间将被释放。感谢您的响应。我想知道为什么我的表中的索引如此之大,即使在吸尘器清理之后也感谢您的回复。我想知道为什么我的表中的索引即使在吸尘之后也会这么大