我一直在对各种 postgres SQL 查询进行一些测试。
测试通常涉及更改查询的语法、更改表连接或偶尔完全重写查询。
我注意到有时我会得到“明显”的大幅性能提升。我将运行一个查询,运行需要(比如)60 秒,我会做一个小改动,然后运行(比如)5 秒。
起初我认为这是因为我的小调整提高了性能。我已经意识到实际上必须有一些缓存正在进行,(要看到这一点,请尝试运行 60 秒的查询,然后几秒钟后再次运行它 - 它总是第二次运行得更快),我假设这个是因为数据已经在本地缓存在某处,所以当数据需要第二次读取时,它已经到手了。
我确信这是一个有用的性能特性,但它确实使得在调整查询时很难发现真正的性能改进。是否可以在每次执行之前刷新缓存以确保每个测试从同一位置开始?
谢谢
我有许多 postgres 表,其中有一列类型为 INT,我需要将其更改为 BIGINT。表的每个分区包含大约 1 亿行,我的目的是分离各个分区并更改列类型,然后重新附加。
我的问题是,需要更新的列已建立索引。删除索引、更改列类型然后重新创建索引可能会更快吗?或者我应该保留索引并只更改列类型?
请注意,列值不会改变,只会改变数据类型(不确定这是否相关!)
谢谢
如果我运行以下命令
VACUUM myTable;
Run Code Online (Sandbox Code Playgroud)
这被记录在 postgres 系统表中,可以通过以下命令查看
select last_vacuum, vacuum_count from pg_stat_all_tables where relname= 'mytable';
Run Code Online (Sandbox Code Playgroud)
然而,这样做VACUUM FULL
似乎没有被记录下来。
我如何知道最后一次VACUUM FULL
对表运行的时间?
如果我创建一个表和这样的分区......
CREATE TABLE tab1 (a int, b int) PARTITION BY RANGE(a);
CREATE TABLE tab1_p1 PARTITION OF tab1 FOR VALUES FROM (0) TO (100);
CREATE TABLE tab1_p2 PARTITION OF tab1 FOR VALUES FROM (100) TO (200);
Run Code Online (Sandbox Code Playgroud)
我如何随后检查范围?我试过浏览 information_schema.tables 和 information_schema.table_constraints 但到目前为止没有运气。
我刚刚完成了对现有表的分区,方法是 1) 重命名原始表 2) 创建一个与原始表具有相同结构的新分区表,以及 3) 将数据从旧的未分区表传输到新表。
分区工作得很好,没有问题。唯一的问题是我现在有两个具有相同字段的表,它们都使用相同的序列
ident integer NOT NULL DEFAULT nextval('mytable_ident_seq'::regclass)
Run Code Online (Sandbox Code Playgroud)
问题 - 如何删除原始表格?
我无法删除原始表,因为这样做 Postgres 会尝试删除序列,这会导致错误,因为“其他对象依赖于它”,而“其他对象”是我新创建的分区版本。
我尝试的第一件事是删除对序列的引用
ALTER TABLE mytable_old ALTER COLUMN ident SET DEFAULT 0;
Run Code Online (Sandbox Code Playgroud)
这似乎有效,它没有返回任何错误,但是当我查看该字段的属性时,它仍然说它依赖于序列,当我尝试删除表时,我得到了同样的错误。该表目前有零行数据,我已经删除了除这一行之外的所有字段,但我仍然无法实际删除表本身。
这不是一个严重错误,数据库工作正常,新版本的表已分区并且工作正常,为了整洁,我只想删除旧表。
我知道在表上执行 VACUUM FULL 将释放磁盘空间并将其返回给操作系统。
有几次我的操作系统(Windows)警告我它的磁盘空间不足。我的反应是迅速关闭我所能做的一切,并在其中一个更活跃的表上运行 VACUUM FULL。
我注意到 VACUUM FULL 似乎需要至少几百 MB 的空闲空间才能实际工作。如果我在只有 50 MB 的磁盘空间时尝试在 1GB 的表上执行 VACCUM FULL,那么这很快就会消失,我的计算机很快就会停止,而 VACUUM FULL 将无法工作。
当我知道有未使用的空间可用但没有足够的空间来运行 VACUUM 时,如何释放 POSTGRES 数据库中的操作系统空间?
(我知道正确的答案是——“不要傻到一开始就让它发生”,但 sh1t 偶尔会发生!)
我需要在一个包含大约 6 亿行的现有表上插入一个新的两字段索引。该表包含大约一年内积累的数据,每天大约添加 200 万行新行。
\n\n我知道一次性向一个非常大的表添加新索引需要很长时间,因此为了节省时间,我首先使用以下命令仅对最后几天的数据建立索引\xe2\x80\xa6
\n\nCREATE INDEX idx_001\nON message (deviceNumber, messageTime)\nWHERE messageTime >='07-May-2018 00:00:00' ;\n
Run Code Online (Sandbox Code Playgroud)\n\n一天索引大约需要 3 小时,即大约 40 分钟。
\n\n理想情况下,我\xe2\x80\x99d 喜欢对整个表建立索引,但如果一天的数据需要 40 分钟,一次性完成将需要一周以上的时间。
\n\n我想我可以创建很多小索引,每个索引用于几天的数据,也许像这样\xe2\x80\xa6
\n\nCREATE INDEX idx_002\nON message (deviceNumber, messageTime)\nWHERE messageTime <'07-May-2018 00:00:00' AND messageTime >='01-May-2018 00:00:00' ;\n
Run Code Online (Sandbox Code Playgroud)\n\n但我\xe2\x80\x99d 更喜欢坚持使用一个索引。有没有办法改变现有索引的 where 子句来增加覆盖天数?或者我必须创建很多小索引吗?
\n在大型表上运行 VACUUM FULL之前,是否可以检查表空间中有多少可用的可重用空间?
我有一个很大的 postgres 表(大约 20G),偶尔会出现 VACUUM FULL 的情况。该驱动器上的可用空间在 15-25 GB 之间变化。在尝试每次真空之前,我都会记录表大小(使用 postgres 查询)和可用磁盘空间(使用操作系统工具)。
我知道 VACUUM FULL 需要对表进行完整复制。因此,如果表为 20G,则需要 20G 的可用空间。
有时表有 20G,只有 15G 操作系统空间可用,真空将起作用。我猜所需的额外 5G 是从表空间内部恢复的。
其他时候,vacuum 会由于空间不足而失败,我猜在这些情况下,表空间中找不到所需的额外 5G。
我希望能够事先检查是否有足够的空间用于 VACUUM FULL,我该怎么做?我知道表有多大,我知道操作系统有多少可用空间,但我不知道表空间中有多少可重复利用的空间。
是否可以编写一个UPDATE
查询,如果它尝试更改的记录被另一个进程锁定(而不是等待锁被释放),则该查询将简单地退出?
我有一个进程应该更新表中的记录,有时这些记录会被锁定。更新这些记录是可取的,但不是必需的。如果记录正在使用中,我宁愿我的流程忘记更新并继续处理更重要的事情。
我当前的方法是将命令超时设置为 1 秒,但即使这也比我想要等待的时间长 - 正常更新需要不到一毫秒,因此等待一秒是一个主要开销。
鉴于这样创建的表......
CREATE TABLE measurement (
city_id int not null,
logdate date not null,
peaktemp int,
unitsales int
) PARTITION BY RANGE (logdate);
Run Code Online (Sandbox Code Playgroud)
如何确定它被分区在哪一列上?- 在本例中,仅通过查询 postgres 目录来获取“logdate”。
我查看了目录中明显的位置(pg_class、pg_index),但没有任何结果。
(使用10.5版本)
系统表pg_stat_all_tables
记录 autovacuum 守护进程最后一次清理表的时间。
我注意到一些性能问题与数据库中较大的表之一被清理之间可能存在关联。然而,由于我不知道吸尘过程的持续时间,所以我不能 100% 确定。
如何查明在任何给定的表上自动清理花费了多长时间?
postgresql ×11
performance ×5
index ×2
partitioning ×2
disk-space ×1
locking ×1
metadata ×1
tablespaces ×1
update ×1
vacuum ×1