我正在Postegres 8.4上的一个约300万行的桌子上尝试一个简单的UPDATE table SET column1 = 0
,但它需要永远完成。它已运行超过10分钟。现在是我的最后一次尝试。
之前,我试图在该表上运行VACUUM和ANALYZE命令,我也试图创建一些索引(虽然我怀疑这会在这种情况下有所不同)但似乎没有任何帮助。
还有其他想法吗?
谢谢, 里卡多
更新
这是表结构:
CREATE TABLE myTable
(
id bigserial NOT NULL,
title text,
description text,
link text,
"type" character varying(255),
generalFreq real,
generalWeight real,
author_id bigint,
status_id bigint,
CONSTRAINT resources_pkey PRIMARY KEY (id),
CONSTRAINT author_pkey FOREIGN KEY (author_id)
REFERENCES users (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT c_unique_status_id UNIQUE (status_id)
);
我正在尝试运行UPDATE myTable SET generalFreq = 0;
答案 0 :(得分:31)
我必须使用每行的不同值更新1或20亿行的表。每次运行都会产生约1亿次变化(10%)。 我的第一次尝试是将它们直接分配到特定分区上的300K更新事务中,因为如果使用分区,Postgresql并不总是优化准备好的查询。
CREATE TEMP TABLE tempTable (id BIGINT NOT NULL, field(s) to be updated,
CONSTRAINT tempTable_pkey PRIMARY KEY (id));
根据可用的RAM累积缓冲区中的一堆更新 当它填满,或需要更改表/分区,或完成时:
COPY tempTable FROM buffer;
UPDATE myTable a SET field(s)=value(s) FROM tempTable b WHERE a.id=b.id;
COMMIT;
TRUNCATE TABLE tempTable;
VACUUM FULL ANALYZE myTable;
这意味着现在运行需要1.5小时而不是18小时才能进行1亿次更新,包括真空。
答案 1 :(得分:13)
看一下这个答案:PostgreSQL slow on a large table with arrays and lots of updates
首先从更好的FILLFACTOR开始,执行VACUUM FULL强制表重写并在UPDATE查询后检查HOT更新:
SELECT n_tup_hot_upd, * FROM pg_stat_user_tables WHERE relname = 'myTable';
当您要更新大量记录时,HOT更新速度会快得多。有关HOT的更多信息,请参阅此article。
聚苯乙烯。您需要8.3或更高版本。
答案 2 :(得分:7)
等待35分钟后。为了我的UPDATE查询完成(但仍然没有)我决定尝试不同的东西。所以我所做的是一个命令:
CREATE TABLE table2 AS
SELECT
all the fields of table1 except the one I wanted to update, 0 as theFieldToUpdate
from myTable
然后添加索引,然后删除旧表并重命名新表以取代它。那只花了1.7分钟。处理加上一些额外的时间来重新创建索引和约束。但它确实有帮助! :)
当然,这只是因为没有其他人在使用数据库。如果这是在生产环境中,我需要先锁定表。
答案 3 :(得分:2)
今天我花了很多时间处理类似问题。我发现solution:删除了更新前的所有约束/索引。无论要更新的列是否已编制索引,似乎psql都会更新所有更新行的所有索引。更新完成后,再添加约束/索引。
答案 4 :(得分:2)
试试这个(注意generalFreq
以REAL类型开头,并保持不变):
ALTER TABLE myTable ALTER COLUMN generalFreq TYPE REAL USING 0;
这将重写表,类似于DROP + CREATE,并重建所有索引。但一切都在一个命令中。更快(大约2倍)并且您不必处理依赖关系并重新创建索引和其他东西,尽管它确实锁定了表(访问独占 - 即完全锁定)持续时间。或者也许这就是你想要的东西,如果你想让其他一切排在后面。如果您没有更新“太多”行,则这种方式比仅更新更慢。
答案 5 :(得分:1)
我建议的第一件事(来自https://dba.stackexchange.com/questions/118178/does-updating-a-row-with-the-same-value-actually-update-the-row)只是更新"需要"它,例如:
UPDATE myTable SET generalFreq = 0 where generalFreq != 0;
(可能还需要generalFreq上的索引)。然后,您将更新更少的行。虽然不是因为这些值都已经非零,但是更新的行数减少了#34;可以帮助"因为否则它会更新它们和所有索引,无论值是否发生变化。
另一种选择:如果星星在默认值和非空约束方面对齐,您可以删除旧列并仅通过调整元数据即时创建another。
答案 6 :(得分:0)
你是如何运作的?如果您循环每一行并执行更新语句,那么您可能会运行数百万个单独的更新,这就是为什么它的执行速度会非常慢。
如果您在一个语句中为所有记录运行单个更新语句,它将运行得更快,如果此过程很慢,那么它可能比您的硬件更重要。 300万是很多记录。
答案 7 :(得分:0)
在测试中,我注意到即使有一个临时表,超过20万行的大更新比10万行的2个更新要慢。
我的解决方案是循环,在每个循环中创建一个200,000行的临时表,在该表中我计算我的值,然后使用新值aso更新我的主表...
每2000000行,我都手动进行“ VACUUM ANALYZE mytable”,我注意到自动吸尘器并不能完成此类更新。
答案 8 :(得分:-3)
尝试
UPDATE myTable SET generalFreq = 0.0;
也许这是一个演员问题