VACUUM
通常不会将磁盘空间返回给操作系统,除非在某些特殊情况下。
从文档:
VACUUM
删除表和索引中的死行版本并标记可用空间以供将来重用的标准形式。但是,它不会将空间返回给操作系统,除非在表末尾的一个或多个页面完全空闲并且可以轻松获得排他表锁的特殊情况下。相比之下,VACUUM FULL
通过编写一个没有死空间的完整新版本的表文件来主动压缩表。这最大限度地减少了表的大小,但可能需要很长时间。它还需要额外的磁盘空间用于表的新副本,直到操作完成。
问题是:如何实现这个数据库状态one or more pages at the end of a table become entirely free
?这可以通过 完成VACUUM FULL
,但我没有足够的空间来实现它。那么还有没有其他可能呢?
例如,当我使用返回记录 ID 的查询时
INSERT INTO projects(name)
VALUES (name1), (name2), (name3) returning id;
Run Code Online (Sandbox Code Playgroud)
产生输出:
1
2
3
Run Code Online (Sandbox Code Playgroud)
这个 ids 会指向相应的插入值吗?
1 -> name1
2 -> name2
3 -> name3
Run Code Online (Sandbox Code Playgroud) Postgres 系统列记录在第 5 章。数据定义 > 5.4。系统列。
该页面提到oid
值“是 32 位数量”。该页面对交易标识符也有同样的说法。所以我假设这意味着oid
, tableoid
, xmin
, cmin
, xmax
, 和cmax
都是 32 位整数。
但这离开了ctid
系统列。
行版本在其表中的物理位置。请注意,尽管 ctid 可用于非常快速地定位行版本,但如果行的 ctid 被 VACUUM FULL 更新或移动,则该行的 ctid 将更改。因此 ctid 作为长期行标识符是无用的。OID,或者更好的是用户定义的序列号,应该用于标识逻辑行。
? ctid
列的数据类型是什么?
具体来说,我对 Postgres 10.3 版本感兴趣,但如果它在过去的版本中发生了变化,那会很高兴知道。
我有一个表,其架构如下:
create_table "questions_tags", :id => false, :force => true do |t|
t.integer "question_id"
t.integer "tag_id"
end
add_index "questions_tags", ["question_id"], :name => "index_questions_tags_on_question_id"
add_index "questions_tags", ["tag_id"], :name => "index_questions_tags_on_tag_id"
Run Code Online (Sandbox Code Playgroud)
我想删除重复的记录,即它们既具有相同的记录tag_id
又question_id
与另一条记录相同。
SQL 看起来像什么?
我有一个包含数亿行的表,我需要从中删除数据。
现有的索引是最有效的。
但是,我可以使用现有索引通过使用ctid
值查找要删除的行:
DELETE FROM calendar_event WHERE ctid IN
(SELECT ctid FROM calendar_event WHERE user_id = 5 LIMIT 100 FOR UPDATE)
Run Code Online (Sandbox Code Playgroud)
ctid
在这种情况下依赖 的风险是什么?我最糟糕的情况是删除错误的行。
postgresql performance delete concurrency postgresql-performance
假设您有一个具有以下定义的表:
CREATE TABLE public.positions
(
id serial,
latitude numeric(18,12),
longitude numeric(18,12),
updated_at timestamp without time zone
)
Run Code Online (Sandbox Code Playgroud)
您在此表中有 50,000 行。现在出于测试目的,您将运行如下更新:
update positions
set updated_at = now()
where latitude between 234.12 and 235.00;
Run Code Online (Sandbox Code Playgroud)
该语句将从 50,000 行(在此特定数据集中)更新 1,000 行。
如果您在 30 个不同的线程中运行这样的查询*,MySQL innodb 将成功,而 PostgreSQL 将因大量死锁而失败。
为什么?
* 我正在比较最新版本的 MySQL innodb 与 Postgres,这是一个并发更新案例。生产案例:想象有 5000 只库存不断更新,最新价格不断可用。
我正在使用AWS Aurora PostgreSQL Serverless
自动缩放。看起来好像缩放清除了共享缓冲区,所以当我们想要提高性能时,我们被迫面对 I/O 瓶颈。在我们热身之后,我们看到了巨大的性能提升。但是,如果我们在缩放后背靠背运行,则第二次运行会更快。虽然我没有看到任何关于共享缓冲区是否在缩放时被清除的具体信息,但我几乎肯定它是。
Aurora Serverless 目前正在使用PostgreSQL 10.14
,并且支持pg_prewarm
扩展。它看起来像最新的文件显示在服务器重新启动后prewarm支持自动prewarm,但这是无服务器并不会出现提自动预暖的一个版本的文档中。
我发现这篇文章在重新启动服务器或从崩溃中恢复时非常适合 PostgreSQL。
pg_prewarm
支持first_block
和last_block
阻止表/索引的编号,但是如何知道要放入哪些值呢?我们提前知道我们的峰值是什么时候,并告诉 RDS 在此之前进行扩展,因此我们有一个可以准备的时间窗口。
我有哪些选择?
postgresql ×7
aws-aurora ×1
cache ×1
concurrency ×1
datatypes ×1
deadlock ×1
delete ×1
disk-space ×1
duplication ×1
innodb ×1
insert ×1
maintenance ×1
mysql ×1
order-by ×1
performance ×1
vacuum ×1