AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 37028
Accepted
Vadim Samokhin
Vadim Samokhin
Asked: 2013-03-20 07:45:49 +0800 CST2013-03-20 07:45:49 +0800 CST 2013-03-20 07:45:49 +0800 CST

VACUUM 将磁盘空间返回给操作系统

  • 772

VACUUM通常不会将磁盘空间归还给操作系统,除非在某些特殊情况下。
从文档:

VACUUM删除表和索引中的死行版本并标记可用空间以供将来重用的标准形式。但是,它不会将空间返回给操作系统,除非在特殊情况下,表末尾的一个或多个页面变得完全空闲并且可以轻松获得排他表锁。相反,VACUUM FULL通过编写没有死空间的完整新版本的表文件来主动压缩表。这可以最小化表的大小,但可能需要很长时间。它还需要额外的磁盘空间来存储表的新副本,直到操作完成。

问题是:如何实现这个数据库状态one or more pages at the end of a table become entirely free?这可以通过 来完成VACUUM FULL,但我没有足够的空间来实现它。那么还有其他可能吗?

postgresql postgresql-9.2
  • 1 1 个回答
  • 43749 Views

1 个回答

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2013-03-20T08:22:48+08:002013-03-20T08:22:48+08:00

    要将空间返回给操作系统,请使用VACUUM FULL. 在这期间,我想你会跑VACUUM FULL ANALYZE。我引用手册:

    FULL

    选择“full”vacuum,可以回收更多空间,但需要更长的时间并且会独占锁定表。此方法还需要额外的磁盘空间,因为它会写入表的新副本并且在操作完成之前不会释放旧副本。通常这应该只在需要从表中回收大量空间时使用。

    大胆强调我的。

    CLUSTER作为附带效应,也实现了这一点。

    PlainVACUUM通常无法实现您的目标(“表格末尾的一个或多个页面完全免费”)。当机会出现时,它不会重新排序行,只会从文件的物理末尾修剪空页面 - 就像您从手册中引用的那样。

    当您在附加其他元组之前获得INSERT一批行和它们时,您可以在物理文件的末尾获得空页。DELETE或者,如果删除了足够多的行,这可能是巧合。

    还有一些特殊设置可能会阻止VACUUM FULL回收空间。看:

    • 如何针对非常高频的更新优化表?

    在表格末尾准备空白页以进行测试

    系统列ctid代表一行的物理位置。您需要了解该列:

    • 如何将 ctid 分解为页码和行号?

    我们可以使用它并通过从最后一页删除所有行来准备一个表:

    DELETE FROM tbl t
    USING (
       SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid     AS min_tid
            , (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
       FROM   tbl
       ORDER  BY ctid DESC
       LIMIT  1
       ) d
    WHERE  t.ctid BETWEEN d.min_tid AND d.max_tid;
    

    现在,最后一页是空的。这忽略了并发写入。要么您是唯一一个写入该表的人,要么您需要获取写锁以防止出现竞争条件。

    该查询经过优化,可以快速识别符合条件的行。a 的第二个数字tid是存储为 unsigned 的元组索引int2,并且65535是该类型 ( 2^16 - 1) 的最大值,因此这是安全的上限。

    db<>fiddle here (重用不同情况下的简单表。)
    旧的 sqlfiddle

    测量行/表大小的工具:

    • 测量 PostgreSQL 表行的大小

    磁盘已满

    对于任何这些操作,您都需要在磁盘上留出回旋余地。还有社区工具pg_repack可以替代VACUUM FULL/ CLUSTER。它避免了独占锁,但也需要可用空间来使用。手册:

    需要两倍于目标表和索引的可用磁盘空间。

    作为最后的手段,您可以运行转储/恢复周期。这也消除了表和索引中的所有膨胀。密切相关的问题:

    • 我需要在没有可用磁盘空间的情况下运行 VACUUM FULL

    那边的答案相当激进。如果您的情况允许(没有外键或其他引用阻止行删除),并且没有对表的并发访问),您可以:

    将表转储到从具有大量磁盘空间的远程计算机连接的磁盘(for ):-a--data-only

    从远程 shell,转储表数据:

    pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql
    

    在 pg 会话中,TRUNCATE该表:

    -- drop all indexes and constraints here for best performance
    TRUNCATE mytbl;
    

    从远程 shell,恢复到同一个表:

    psql -h <host_name> -p <port> mydb -f db_mytbl.sql
    -- recreate all indexes and constraints here
    

    它现在没有任何死行或膨胀。

    但也许你可以更简单?

    • 您可以通过删除(移动)不相关的文件在磁盘上腾出足够的空间吗?

    • 您可以VACUUM FULL先一张一张地缩小表,从而释放足够的磁盘空间吗?

    • 您可以运行REINDEX TABLE或REINDEX INDEX从臃肿的索引中释放磁盘空间吗?

    无论做什么,都不要轻举妄动。如有疑问,请先将所有内容备份到安全位置。

    • 53

相关问题

  • 我可以在使用数据库后激活 PITR 吗?

  • 运行时间偏移延迟复制的最佳实践

  • 存储过程可以防止 SQL 注入吗?

  • PostgreSQL 中 UniProt 的生物序列

  • PostgreSQL 9.0 Replication 和 Slony-I 有什么区别?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    授予用户对所有表的访问权限

    • 5 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve