Received: from maia.hub.org (unknown [200.46.204.183]) by mail.postgresql.org (Postfix) with ESMTP id C7C88633BD1 for ; Thu, 7 Jan 2010 13:46:49 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 38431-01-2 for ; Thu, 7 Jan 2010 17:46:38 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from outbound-mail-342.bluehost.com (outbound-mail-342.bluehost.com [66.147.249.3]) by mail.postgresql.org (Postfix) with SMTP id CFC3E633A34 for ; Thu, 7 Jan 2010 13:46:30 -0400 (AST) Received: (qmail 21257 invoked by uid 0); 7 Jan 2010 17:46:29 -0000 Received: from unknown (HELO box498.bluehost.com) (66.147.242.98) by outboundproxy7.bluehost.com.bluehost.com with SMTP; 7 Jan 2010 17:46:29 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=consistentstate.com; h=Received:From:Organization:To:Subject:Date:User-Agent:References:In-Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding:Message-Id:X-Identified-User; b=QF/C5dNKvbhX0udt5fuwM1zxiVcIo241dpNjYi1xpCn+oYKxB0Z1D51vjTQAMycjfIWcA1bIfirqhqVZD2j8aZpxIIKUx8WwiR6DH7hF5kn8Us+9NlByj3Rab3ZiPDTZ; Received: from c-67-176-12-8.hsd1.co.comcast.net ([67.176.12.8] helo=issac.consistentstate.com) by box498.bluehost.com with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.69) (envelope-from ) id 1NSwRI-0006B5-Ul for pgsql-performance@postgresql.org; Thu, 07 Jan 2010 10:46:29 -0700 From: Kevin Kempter Organization: Consistent State To: pgsql-performance@postgresql.org Subject: Re: Massive table (500M rows) update nightmare Date: Thu, 7 Jan 2010 10:46:24 -0700 User-Agent: KMail/1.12.4 (Linux/2.6.31.9-174.fc12.x86_64; KDE/4.3.4; x86_64; ; ) References: <4B45BE14020000250002DEE1@gw.wicourts.gov> <4B45BE37020000250002DEE4@gw.wicourts.gov> <4B45BE37020000250002DEE4@gw.wicourts.gov> In-Reply-To: <4B45BE37020000250002DEE4@gw.wicourts.gov> MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Message-Id: <201001071046.24305.kevink@consistentstate.com> X-Identified-User: {3049:box498.bluehost.com:consist3:consistentstate.com} {sentby:smtp auth 67.176.12.8 authed with kevink@consistentstate.com} X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=3.318 tagged_above=-10 required=5 tests=BAYES_40=-0.185, FH_DATE_PAST_20XX=3.188, SARE_MILLIONSOF=0.315 X-Spam-Level: *** X-Archive-Number: 201001/109 X-Sequence-Number: 36989 On Thursday 07 January 2010 09:57:59 Kevin Grittner wrote: > Ludwik Dylag wrote: > > I would suggest: > > 1. turn off autovacuum > > 1a. ewentually tune db for better performace for this kind of > > operation (cant not help here) > > 2. restart database > > 3. drop all indexes > > 4. update > > 5. vacuum full table > > 6. create indexes > > 7. turn on autovacuum > > I've only ever attempted something like that with a few tens of > millions of rows. I gave up on waiting for the VACUUM FULL step > after a few days. > > I some scheduled down time is acceptable (with "some" kind of hard > to estimate accurately) the best bet would be to add the column with > the USING clause to fill in the value. (I think that would cause a > table rewrite; if not, then add something to the ALTER TABLE which > would.) My impression is that the OP would rather stretch out the > implementation than to suffer down time, which can certainly be a > valid call. > > If that is the goal, then the real question is whether there's a way > to tune the incremental updates to speed that phase. Carlo, what > version of PostgreSQL is this? Can you show us the results of an > EXPLAIN ANALYZE for the run of one iteration of the UPDATE? > Information on the OS, hardware, PostgreSQL build configuration, and > the contents of postgresql.conf (excluding all comments) could help > us spot possible techniques to speed this up. > > -Kevin > If you can come up with an effective method of tracking updates/deletes/inserts such as a trigger that writes the PK to a separate table upon any inserts, updates or deletes to the table you could do something like this: 1) create new table (no indexes) with the structure you want the table to have at the end of the process (i.e. the post-altered state) [new_tab] 2) create the insert,update,delete triggers mentioned above on the existing table [curr_tab] and write all the PK id's that change into a 3rd table [changed_keys] 3) kick off a process that simply does a select from curr_tab into new_tab and populates/back-fills the new column as part of the query 4) let it run as long as it takes 5) once it's complete do this: Create the all the indexes on the new_tab BEGIN; LOCK TABLE curr_tab; DELETE from new_tab where pk_id in (select distinct pk_id from changed_keys); INSERT into new_tab select * from curr_tab where curr_tab.pk_id in (select distinct pk_id from changed_keys); ALTER TABLE curr_tab RENAME to old_tab; ALTER TABLE new_tab RENAME to curr_tab; COMMIT; Also you might want to consider partitioning this table in the process... Once you're confident you no longer need the old table [old_tab] you can drop it