Re: VACUUM FULL versus CLUSTER ON

Lists: pgsql-general
From: Sven Willenberger <sven(at)dmv(dot)com>
To: Postgres general mailing list <pgsql-general(at)postgresql(dot)org>
Subject: VACUUM FULL versus CLUSTER ON
Date: 2006-07-07 15:19:18
Message-ID: 1152285558.32676.9.camel@lanshark.dmv.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Postgresql 8.0.4 on FreeBSD 5.4

I have a table consisting of some 300million rows that, every couple of
months, has 100 million rows deleted from it (an immediately vacuumed
afterward). Even though it gets routinely vacuumed (the only
deletions/updates are just the quarterly ones), the freespace map was
not increased in size to keep up with the growing size of the other
tables in the database which do experience many updates,etc.

I suspect that the table is suffering from bloat (not the indexes though
as I drop them prior to the huge delete, then create them anew). What
would be the recommended method for reclaiming the disk space lost due
to bloat? Dropping the 5 indexes on the table and doing a VACUUM FULL,
keeping the indexes and doing a VACUUM FULL (does FULL perform the same
disk moving operations on the indexes as it does on the actual table?),
dropping the indexes except the primary key and CLUSTER ON primary key,
keeping the indexes and doing a CLUSTER ON primary key (again, does
CLUSTER ON just operation on the table proper?)

What are the caveats on using one over the other? I imagine any of the
options I listed above will involve a full table lock. Are there any
differences in the amount of free disk space required for each method?

Thanks,

Sven


From: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
To: Sven Willenberger <sven(at)dmv(dot)com>
Cc: Postgres general mailing list <pgsql-general(at)postgresql(dot)org>
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-07 16:00:27
Message-ID: 1152288027.4948.5.camel@coppola.muc.ecircle.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

[snip]
> as I drop them prior to the huge delete, then create them anew). What
> would be the recommended method for reclaiming the disk space lost due
> to bloat? Dropping the 5 indexes on the table and doing a VACUUM FULL,
> keeping the indexes and doing a VACUUM FULL (does FULL perform the same
> disk moving operations on the indexes as it does on the actual table?),
> dropping the indexes except the primary key and CLUSTER ON primary key,
> keeping the indexes and doing a CLUSTER ON primary key (again, does
> CLUSTER ON just operation on the table proper?)

I won't know for sure, but I guess the least downtime you would get by
not dropping the indexes before the delete, but do a reindex after it.
Then cluster on the primary key...

My reasoning (correct me if I'm wrong): the deletion speed won't be
affected by the indexes, I think deletions don't touch the indexes at
all. The REINDEX command recreates all indexes at once, I think it needs
only one full table scan. That needs the indexes in place, so you
shouldn't drop them. The CLUSTER is a lot faster than VACUUM FULL. The
only problem could be that I think all these operations might take more
disk space than the individual indexing + VACUUM FULL.

Are my assumptions correct ?

Cheers,
Csaba.


From: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>
To: pgsql-general(at)postgresql(dot)org
Cc: Sven Willenberger <sven(at)dmv(dot)com>
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-07 16:55:32
Message-ID: 200607070955.32939.jd@commandprompt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Friday 07 July 2006 08:19, Sven Willenberger wrote:
> Postgresql 8.0.4 on FreeBSD 5.4
>
> I have a table consisting of some 300million rows that, every couple of
> months, has 100 million rows deleted from it (an immediately vacuumed
> afterward). Even though it gets routinely vacuumed (the only
> deletions/updates are just the quarterly ones), the freespace map was
> not increased in size to keep up with the growing size of the other
> tables in the database which do experience many updates,etc.

Based on the size of the table, you may want to:

Backup the table
Drop the table
Restore the table

Is is possible that this will be faster in this instance.

Secondly this sounds like a perfect time for you to consider upgrading to 8.1
and making use of table partitioning. That way you can just truncate the child
table containing the old data.

Sincerely,

Joshua D. Drake


From: Greg Stark <gsstark(at)mit(dot)edu>
To: Csaba Nagy <nagy(at)ecircle-ag(dot)com>
Cc: Sven Willenberger <sven(at)dmv(dot)com>, Postgres general mailing list <pgsql-general(at)postgresql(dot)org>
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-07 16:57:51
Message-ID: 874pxtmjxs.fsf@stark.xeocode.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Csaba Nagy <nagy(at)ecircle-ag(dot)com> writes:

> I won't know for sure, but I guess the least downtime you would get by
> not dropping the indexes before the delete, but do a reindex after it.
> Then cluster on the primary key...
>
> My reasoning (correct me if I'm wrong): the deletion speed won't be
> affected by the indexes, I think deletions don't touch the indexes at
> all.

That's true, more or less. I think there's a small hit actually as queries set
the hint bit and the pages have to be flushed.

As long as you're just deleting and not inserting or updating

> The REINDEX command recreates all indexes at once, I think it needs
> only one full table scan.

No, each index build has to do its own full scan. It wouldn't save much
anyways not to, where would you store the tuples in the meantime? And why
would this temporary storage place be any faster than scanning the original
table?

--
greg


From: Sven Willenberger <sven(at)dmv(dot)com>
To: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-07 17:26:14
Message-ID: 1152293174.32676.17.camel@lanshark.dmv.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Fri, 2006-07-07 at 09:55 -0700, Joshua D. Drake wrote:
> On Friday 07 July 2006 08:19, Sven Willenberger wrote:
> > Postgresql 8.0.4 on FreeBSD 5.4
> >
> > I have a table consisting of some 300million rows that, every couple of
> > months, has 100 million rows deleted from it (an immediately vacuumed
> > afterward). Even though it gets routinely vacuumed (the only
> > deletions/updates are just the quarterly ones), the freespace map was
> > not increased in size to keep up with the growing size of the other
> > tables in the database which do experience many updates,etc.
>
> Based on the size of the table, you may want to:
>
> Backup the table
> Drop the table
> Restore the table
>
> Is is possible that this will be faster in this instance.
>
> Secondly this sounds like a perfect time for you to consider upgrading to 8.1
> and making use of table partitioning. That way you can just truncate the child
> table containing the old data.
>
> Sincerely,
>
> Joshua D. Drake

Doing a quick check reveals that the relation in question currently
consumes 186GB of space (which I highly suspect is largely bloat). The
delete was just run this past weekend as was the recreation of the
indexes. I have 50GB of disk space left; If I vacuum full, it does not
need to create a temporary copy of the relation and indexes like cluster
does, does it? At this point, I think CLUSTER ON is out of the question
due to the need to create the temporary table and indexes (I will run
out of space during the operation).

I do plan on migrating the whole mess to a new server which will run 8.1
(I had looked at inheritance for partitioning, I am glad to see that 8.1
took the concept and ran with it further :) ) This new server will use
an external SAS array so I should simply be able to add another array as
the need arises and partition to it via tablespace.

Thanks to all who offered suggestions; it would appear that at this
stage my only option to buy some time is try a vacuum full. My final
question: can I leave the indexes in place when I vacuum full? I assume
this will only operate on the table itself?

Sven


From: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>
To: pgsql-general(at)postgresql(dot)org
Cc: Sven Willenberger <sven(at)dmv(dot)com>
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-07 17:41:25
Message-ID: 200607071041.25714.jd@commandprompt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general


> > Sincerely,
> >
> > Joshua D. Drake
>
> Doing a quick check reveals that the relation in question currently
> consumes 186GB of space (which I highly suspect is largely bloat).

Good lord.. .186 gig for a 300 million row table? Unless those are seriously
large rows, you have a TON of bloat.

Joshua D. Drake

--
=== The PostgreSQL Company: Command Prompt, Inc. ===
Sales/Support: +1.503.667.4564 || 24x7/Emergency: +1.800.492.2240
Providing the most comprehensive PostgreSQL solutions since 1997
http://www.commandprompt.com/


From: Sven Willenberger <sven(at)dmv(dot)com>
To: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-07 17:52:58
Message-ID: 1152294779.32676.20.camel@lanshark.dmv.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Fri, 2006-07-07 at 10:41 -0700, Joshua D. Drake wrote:
> > > Sincerely,
> > >
> > > Joshua D. Drake
> >
> > Doing a quick check reveals that the relation in question currently
> > consumes 186GB of space (which I highly suspect is largely bloat).
>
> Good lord.. .186 gig for a 300 million row table? Unless those are seriously
> large rows, you have a TON of bloat.
>
> Joshua D. Drake
>

Yes, that number came from the dbsize functions (in contrib) so I don't
know if that includes the associated indexes as well. The rows are
fairly large, yes, but not enough (IMO) to account for that size. It
will be interesting to see the final size after the vacuum full (which
is the method I have settled on to reclaim space this go round).

Sven


From: Sven Willenberger <sven(at)dmv(dot)com>
To: Sven Willenberger <sven(at)dmv(dot)com>
Cc: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>, pgsql-general(at)postgresql(dot)org
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-08 06:31:37
Message-ID: 44AF5149.9060200@dmv.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Sven Willenberger presumably uttered the following on 07/07/06 13:52:
> On Fri, 2006-07-07 at 10:41 -0700, Joshua D. Drake wrote:
>>>> Sincerely,
>>>>
>>>> Joshua D. Drake
>>> Doing a quick check reveals that the relation in question currently
>>> consumes 186GB of space (which I highly suspect is largely bloat).
>> Good lord.. .186 gig for a 300 million row table? Unless those are seriously
>> large rows, you have a TON of bloat.
>>
>> Joshua D. Drake
>>
>
> Yes, that number came from the dbsize functions (in contrib) so I don't
> know if that includes the associated indexes as well. The rows are
> fairly large, yes, but not enough (IMO) to account for that size. It
> will be interesting to see the final size after the vacuum full (which
> is the method I have settled on to reclaim space this go round).
>
> Sven
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 9: In versions below 8.0, the planner will ignore your desire to
> choose an index scan if your joining column's datatypes do not
> match

Unfortunately it would appear that I cannot vacuum full either as I get an out of
memory error:

# - Memory -

shared_buffers = 5000 # min 16, at least max_connections*2, 8KB each
work_mem = 131072 # min 64, size in KB
maintenance_work_mem = 524288 # min 1024, size in KB
max_stack_depth = 4096 # min 100, size in KB

/boot/loader.conf
kern.maxdsiz="1610612736"
kern.dfldsiz="891289600"

I have disabled other connections to the db except for slony (which will not access
the table in question). I begin a Vacuum full <tablename> and start watching memory
use constantly increase (top). It pushes to:

PID USERNAME PRI NICE SIZE RES STATE C TIME WCPU CPU COMMAND
61048 pgsql -4 0 1640M 1472M getblk 1 6:58 16.75% 16.75% postgres

and then it bails:
ERROR: out of memory
DETAIL: Failed on request of size 78.

Server version is 8.03

Is this a known issue?

Sven


From: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>
To: Sven Willenberger <sven(at)dmv(dot)com>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-08 15:20:15
Message-ID: 200607080820.15511.jd@commandprompt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

>
> Unfortunately it would appear that I cannot vacuum full either as I get an
> out of memory error:
>
>
> # - Memory -
>
> shared_buffers = 5000 # min 16, at least max_connections*2, 8KB
> each work_mem = 131072 # min 64, size in KB
> maintenance_work_mem = 524288 # min 1024, size in KB
> max_stack_depth = 4096 # min 100, size in KB

You could decrease your maintenance_work_mem,

But honestly, at this point I would do the backup restore method.

Joshua D. Drake

--
=== The PostgreSQL Company: Command Prompt, Inc. ===
Sales/Support: +1.503.667.4564 || 24x7/Emergency: +1.800.492.2240
Providing the most comprehensive PostgreSQL solutions since 1997
http://www.commandprompt.com/


From: Scott Marlowe <smarlowe(at)g2switchworks(dot)com>
To: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>
Cc: Sven Willenberger <sven(at)dmv(dot)com>, pgsql general <pgsql-general(at)postgresql(dot)org>
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-10 15:50:26
Message-ID: 1152546626.6540.1.camel@state.g2switchworks.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Sat, 2006-07-08 at 10:20, Joshua D. Drake wrote:
> >
> > Unfortunately it would appear that I cannot vacuum full either as I get an
> > out of memory error:
> >
> >
> > # - Memory -
> >
> > shared_buffers = 5000 # min 16, at least max_connections*2, 8KB
> > each work_mem = 131072 # min 64, size in KB
> > maintenance_work_mem = 524288 # min 1024, size in KB
> > max_stack_depth = 4096 # min 100, size in KB
>
> You could decrease your maintenance_work_mem,
>
> But honestly, at this point I would do the backup restore method.

Also, this kind of points out that you might not have enough swap
space. On most database servers there's enough hard drive space laying
about to have as large a swap space as you'd like, and I can't count the
number of times a large swap has given me enough to time to catch
runaway processes and keep an ailing server up and running, albeit
hobbling along, rather than having to worry about running out of virtual
memory.

Unless the memory being allocated here just has to be real memory. But
I'm guessing not. Sure, swapping is slow, but at least it will let some
memory hungry processes finish.


From: Sven Willenberger <sven(at)dmv(dot)com>
To: Scott Marlowe <smarlowe(at)g2switchworks(dot)com>
Cc: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>, pgsql general <pgsql-general(at)postgresql(dot)org>
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-10 16:04:48
Message-ID: 1152547488.3087.5.camel@lanshark.dmv.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

On Mon, 2006-07-10 at 10:50 -0500, Scott Marlowe wrote:
> On Sat, 2006-07-08 at 10:20, Joshua D. Drake wrote:
> > >
> > > Unfortunately it would appear that I cannot vacuum full either as I get an
> > > out of memory error:
> > >
> > >
> > > # - Memory -
> > >
> > > shared_buffers = 5000 # min 16, at least max_connections*2, 8KB
> > > each work_mem = 131072 # min 64, size in KB
> > > maintenance_work_mem = 524288 # min 1024, size in KB
> > > max_stack_depth = 4096 # min 100, size in KB
> >
> > You could decrease your maintenance_work_mem,
> >
> > But honestly, at this point I would do the backup restore method.
>
> Also, this kind of points out that you might not have enough swap
> space. On most database servers there's enough hard drive space laying
> about to have as large a swap space as you'd like, and I can't count the
> number of times a large swap has given me enough to time to catch
> runaway processes and keep an ailing server up and running, albeit
> hobbling along, rather than having to worry about running out of virtual
> memory.
>
> Unless the memory being allocated here just has to be real memory. But
> I'm guessing not. Sure, swapping is slow, but at least it will let some
> memory hungry processes finish.

The box has 8G of RAM and 10G swap space available to it (almost none of
which touched). The problem was that the VACUUM FULL process never
released any memory. With maintenance work mem set to 512MB, I would
think that it would be enforced such that any given connection would
only be allowed 512MB for maintenance. Why it it growing beyond the 1.5G
I allow system-wide for any given process eludes me right now (and why I
suspect a bad memory leak).

As per the other suggestions, I will end up doing a pg_dump/restore to
reclaim the lost space.

Sven


From: Lincoln Yeoh <lyeoh(at)pop(dot)jaring(dot)my>
To: Scott Marlowe <smarlowe(at)g2switchworks(dot)com>
Cc: pgsql general <pgsql-general(at)postgresql(dot)org>
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-10 16:33:43
Message-ID: 5.2.1.1.1.20060710235655.01d696a0@localhost
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

At 10:50 AM 7/10/2006 -0500, Scott Marlowe wrote:

>On Sat, 2006-07-08 at 10:20, Joshua D. Drake wrote:
> > >
> > > Unfortunately it would appear that I cannot vacuum full either as I
> get an
> > > out of memory error:
>
>Also, this kind of points out that you might not have enough swap
>space. On most database servers there's enough hard drive space laying
>about to have as large a swap space as you'd like, and I can't count the
>number of times a large swap has given me enough to time to catch
>runaway processes and keep an ailing server up and running, albeit
>hobbling along, rather than having to worry about running out of virtual
>memory.

In my opinion, there is not enough real memory, or postgresql (or something
else) is using more memory than it should.

Because I prefer the reverse - processes die rather than the entire server
hobble along while your ssh connection attempts (or other arguably
important stuff) keep timing out. Of course some O/Ses appear to randomly
kill processes when out of memory. BTW, I regard any O/S that kills
critical processes such as the disk syncing processes or swap, or "initd"
in _typical_ out-of-memory scenarios as a product of shoddy workmanship.

I'd prefer just enough swap[1] that when maxed out the server is just
slowed enough to be noticeable, rather than effectively dead and
continuously "running" like a "drum memory" computer.

If a normal userland program cannot handle being killed because there is
not enough memory, then I think something is wrong somewhere (e.g. the O/S
is doing stuff like SIGKILLing postgresql, or postgresql is not handling
SIGTERM properly).

Link.

[1] How much is enough? My guess is that the suitable size would be related
to the random read/write throughput from/to the swap, and the largest worst
case amount of memory that would have to be continuously read and written,
and how long you would be willing to wait. If you have programs that
allocate tons of memory but don't ever actually use the full amount, you
can adjust your swap accordingly.


From: "Joshua D(dot) Drake" <jd(at)commandprompt(dot)com>
To: Sven Willenberger <sven(at)dmv(dot)com>
Cc: Scott Marlowe <smarlowe(at)g2switchworks(dot)com>, pgsql general <pgsql-general(at)postgresql(dot)org>
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-10 16:36:26
Message-ID: 200607100936.26754.jd@commandprompt.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general


> The box has 8G of RAM and 10G swap space available to it (almost none of
> which touched). The problem was that the VACUUM FULL process never
> released any memory. With maintenance work mem set to 512MB, I would
> think that it would be enforced such that any given connection would
> only be allowed 512MB for maintenance. Why it it growing beyond the 1.5G
> I allow system-wide for any given process eludes me right now (and why I
> suspect a bad memory leak).

My understanding is that the maintenance_work_mem is the amount of RAM
that can be used before PostgreSQL swaps out to disk. This is not the amount
of memory that vacuum full will use. Vacuum full is going to use whatever it
needs to get the job done, and on the table your dealing with, its going to
be alot.

> As per the other suggestions, I will end up doing a pg_dump/restore to
> reclaim the lost space.

You already know my opinion on that ;)

Sincerely,

Joshua D. Drake

>
> Sven

--
=== The PostgreSQL Company: Command Prompt, Inc. ===
Sales/Support: +1.503.667.4564 || 24x7/Emergency: +1.800.492.2240
Providing the most comprehensive PostgreSQL solutions since 1997
http://www.commandprompt.com/


From: Joseph Shraibman <jks(at)selectacast(dot)net>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-12 18:54:54
Message-ID: e93ghs$2mq9$1@news.hub.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Joshua D. Drake wrote:

> Secondly this sounds like a perfect time for you to consider upgrading to 8.1
> and making use of table partitioning.

How does that work, exactly?


From: Joseph Shraibman <jks(at)selectacast(dot)net>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-12 19:40:09
Message-ID: e93j6m$1a90$1@news.hub.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

NM I found the documentation.

Joseph Shraibman wrote:
> Joshua D. Drake wrote:
>
>> Secondly this sounds like a perfect time for you to consider upgrading
>> to 8.1
>> and making use of table partitioning.
>
>
> How does that work, exactly?


From: Francisco Reyes <lists(at)stringsutils(dot)com>
To: Sven Willenberger <sven(at)dmv(dot)com>
Cc: Joshua D(dot) Drake <jd(at)commandprompt(dot)com>, pgsql-general(at)postgresql(dot)org
Subject: Re: VACUUM FULL versus CLUSTER ON
Date: 2006-07-31 19:43:31
Message-ID: cone.1154375011.136415.69955.5001@35st-server.simplicato.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-general

Sven Willenberger writes:

> I do plan on migrating the whole mess to a new server which will run 8.1
> (I had looked at inheritance for partitioning, I am glad to see that 8.1
> took the concept and ran with it further

Coming late to the thread..
If you do consider inheritance be aware that some replication methods will
not work with it.