我在 postgres 上运行了一个巨大的查询,其中一个连接表总是进行顺序扫描。列上的索引存在,而 postgres 没有使用它。我做了一个真空分析,然后 postgres 查询计划立即更改为进行索引扫描。
我的问题是进行真空分析的最有效方法是什么。它锁定表吗?如果是这样,您如何真空分析实时生产表?
在PostgreSQL 9.5中,我决定创建一个物化视图“效果”,并计划每小时进行一次并发刷新,因为我希望它始终可用:
REFRESH MATERIALIZED VIEW CONCURRENTLY effects;
Run Code Online (Sandbox Code Playgroud)
在开始的时候,一切都运行良好,我的实例化视图令人耳目一新,磁盘空间使用大致保持不变。
但是,一段时间后,磁盘使用率开始线性增长。
我已经得出结论,这种增长的原因是物化视图,并从该答案中运行查询以得到以下结果:
what | bytes/ct | bytes_pretty | bytes_per_row
-----------------------------------+-------------+--------------+---------------
core_relation_size | 32224567296 | 30 GB | 21140
visibility_map | 991232 | 968 kB | 0
free_space_map | 7938048 | 7752 kB | 5
table_size_incl_toast | 32233504768 | 30 GB | 21146
indexes_size | 22975922176 | 21 GB | 15073
total_size_incl_toast_and_indexes | 55209426944 | 51 GB | 36220
live_rows_in_text_representation | 316152215 | 302 MB | 207
------------------------------ …Run Code Online (Sandbox Code Playgroud) postgresql materialized-views vacuum postgresql-9.5 autovacuum
我有一个非常简单的更新声明:
UPDATE W SET state='thing'
WHERE state NOT IN ('this','that') AND losttime < CURRENT_TIMESTAMP;
Run Code Online (Sandbox Code Playgroud)
表W只有90行,尽管每行大约每10秒钟更新一行的丢失时间和状态列.状态和丢失时间(以及主索引)都有索引.
我注意到大型数据库(即其他表有很多条目,而不是表W)在一段时间内,查询变得越来越慢,越来越慢.运行48小时后,我通过在PqAdminIII的查询窗口中运行它来计时,它需要17分钟才能执行!
我在另一个显示相同问题的表上有类似的查询:
UPDATE H SET release='1'
WHERE a NOT IN (SELECT id from A WHERE state!='done') AND release!='1';
Run Code Online (Sandbox Code Playgroud)
H没有任何索引,但我尝试在H(发布)上放置和删除索引而不改变行为.在数据库已经运行48小时并且表H有大约100k行之后,此查询需要27分钟.Postgres服务器在查询期间将有一个完全挂钩的线程(100%CPU利用率),因此它看起来不像是对网络,磁盘等的任何争用.
因此,从广义上看,我看到的行为是我的数据库按预期运行大约5分钟,然后逐渐停止所有内容,因为基本的维护相关UPDATE命令开始运行的时间越来越长.到第二天,花一个小时做一个简单的维护周期(一些更新),一开始就运行~100ms.我似乎很清楚,性能下降与数据库中的信息量是超线性的 - 可能是N ^ 2或其他一些.
Autovacuum正在使用默认值.我仔细阅读了手册,并没有看到任何跳出来的东西.
我在这里挠头.我没有看到任何在9.0.1和9.0.2发行说明中看起来相关的错误修复.谁能帮我理解发生了什么?谢谢,M
-xxxx-
好的,我可能在这里遇到两个问题.
第一次更新似乎现在运行得很快.不确定发生了什么,所以我将继续假设我需要更频繁地运行VACUUM/ANALYZE或某种组合 - 比如每分钟左右.我真的很想知道为什么autovacuum不会这样做.
第二次更新继续缓慢运行.查询计划表明索引没有得到有效使用,并且发生了80k*30k的交叉,这可能是我似乎正在观察的超线性运行时的原因.(大家都同意这个计划的解释吗?)
我可以将UPDATE转换为SELECT:
SELECT * from H
where a not in (SELECT id from A where state='done') AND release!='1';
Run Code Online (Sandbox Code Playgroud)
具有类似的运行时间(27分钟).
如果我不相信postgres优化器并执行此操作:
WITH r as (select id from A where state='done')
SELECT a from H
JOIN …Run Code Online (Sandbox Code Playgroud) 创建/删除/更新查询时出错:
错误:数据库不接受命令以避免数据库"mydb"中的环绕数据丢失提示:停止postmaster并使用独立后端来清空该数据库.您可能还需要提交或回滚旧准备的事务.
因此,数据库被阻止,只能执行SELECT查询.
数据库的大小为350 GB.1个表(my_table)有大约10亿行.
系统:"x86_64-unknown-linux-gnu上的PostgreSQL 9.3.4,由gcc(GCC)4.4.7 20120313(Red Hat 4.4.7-4)编译,64位"
postgresq.conf的一些设置:
effective_io_concurrency = 15 # 1-1000; 0 disables prefetching
autovacuum_vacuum_cost_delay = -1
#vacuum_cost_delay = 0 # 0-100 milliseconds
#vacuum_cost_page_hit = 1 # 0-10000 credits
#vacuum_cost_page_miss = 10 # 0-10000 credits
#vacuum_cost_page_dirty = 20 # 0-10000 credits
#vacuum_cost_limit = 200
Run Code Online (Sandbox Code Playgroud)
我不使用准备好的交易.但是使用基本的存储过程(这意味着,自动转换,对吧?)每天50mln次.
Сurrently"自动清理:真空分析公共.MY_TABLE(防止环绕)"被perforing,这是近12小时数查询活动.
据我所知,没有真空吸尘器的问题,对吗?
如何解决这个问题并在将来防止这种情况?请帮忙 :)
故事的结尾(约一个月后) 现在我的大表被数千个表分区.每个小桌子都抽真空得快得多.Autovacuum配置设置得更接近默认值.如果需要,我可以再次设置得更加激进,但到目前为止数十亿行的数据库工作得很好.
因此,该主题的问题不应再出现.
ps现在我正在将Postgres-XL视为数据可扩展性的下一步.
我正在使用 PostgreSQL 数据库,并且我想开始VACUUM FULL使用 JPA EntityManager。
版本1
public void doVacuum(){
entityManager.createNativeQuery("VACUUM FULL").executeUpdate()
}
Run Code Online (Sandbox Code Playgroud)
抛出 TransactionRequiredException
版本2
@Transactional
public void doVacuum(){
entityManager.createNativeQuery("VACUUM FULL").executeUpdate()
}
Run Code Online (Sandbox Code Playgroud)
抛出 PersistenceException“VACUUM 无法在事务块内运行”
版本3
public void doVacuum(){
entityManager.createNativeQuery("VACUUM FULL").getResultList()
}
Run Code Online (Sandbox Code Playgroud)
执行真空,但之后我得到 PersistenceException“无结果”
启动这个sql命令的正确方法是什么?
环境:postgres:9.5
表:
segmentation=> \d+ sourceTable;
Table
"sourceTable" Column | Type | Modifiers | Storage | Stats target | Description
-----------------------------+--------------------------+------------------------+----------+--------------+-------------
tracking_id | character varying(40) | not null | extended | |
attributes | jsonb | not null | extended | |
last_modification_timestamp | timestamp with time zone | not null default now() | plain | |
version | bigint | not null default 1 | plain | |
Indexes:
"client_attributes_pkey" PRIMARY KEY, btree (tracking_id)
Run Code Online (Sandbox Code Playgroud)
属性字段为jsonb。它可能是一个巨大的json。因此Postgres创建了TOAST表来存储该列。
TOAST表的统计数据
segmentation=> select * from …Run Code Online (Sandbox Code Playgroud) 我有一个在 PostgreSQL 8.3 上运行的中型数据库集群。
数据库将数字文件(图像)存储为 LOB。
数据库集群中有相当多的活动,大量内容以持续的方式创建和删除。
尽管托管 OID 的应用程序表由应用程序正确维护(当删除映像文件时),数据库集群的大小仍在不断增长。
自动清理功能处于活动状态,因此不应发生这种情况。
最近作为娱乐,我决定开发一个小项目来测试 SQLite 和System.Data.SQLite库提供的 EntityFramework 的好处。
该应用程序有一个数据同步过程,随着时间的推移变得过时,所以我决定从数据库中删除它们。正如预期的那样,删除表行不会减少数据库的大小,因此我决定在其中运行命令 VACUUM。
在阅读了这篇优秀的博客SQLite、VACUUM 和 auto_vacuum 后,我明白了一切,尤其是无法在事务中执行命令这一事实。
就像 Code First 尚不可用一样,我必须使用脚本在数据库中创建表,因此我在同一个地方执行命令。
using (var context = new Context())
{
context.Database.CreateIfNotExists();
context.Database.ExecuteSqlCommand(
"CREATE TABLE IF NOT EXISTS \"main\".\"OutgoingMessages\" (\"Id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"AccountId\" TEXT NOT NULL ON CONFLICT ROLLBACK,\"MessageId\" TEXT NOT NULL ON CONFLICT ROLLBACK,\"Date\" datetime NOT NULL ON CONFLICT ROLLBACK,\"Status\" INTEGER NOT NULL ON CONFLICT ROLLBACK,\"Content\" BLOB NOT NULL ON CONFLICT ROLLBACK,\"Size\" INTEGER NOT NULL ON CONFLICT ROLLBACK,\"Hash\" TEXT …Run Code Online (Sandbox Code Playgroud) 我一直致力于优化数据库中的表。由于清理进程,我们的一张表需要每月进行清理。pg_squeeze 表大小可达 25 GB。由于该表是由生产用户使用的,因此我们无法承受每个月的停机时间来运行VACUUM FULL。
我发现pg_squeeze和pg_repack可以用于此目的。但我无法理解这两者之间的区别。有人可以解释一下有什么区别以及哪个更适合我使用吗?
谢谢。
vacuum ×10
postgresql ×9
sql ×2
.net ×1
autovacuum ×1
c# ×1
database ×1
java ×1
jpa ×1
lob ×1
rdbms ×1
sql-update ×1
sqlite ×1