Pg_upgrade speed for many tables

Started by Bruce Momjianover 13 years ago35 messageshackers
Jump to latest
#1Bruce Momjian
bruce@momjian.us

Magnus reported that a customer with a million tables was finding
pg_upgrade slow. I had never considered many table to be a problem, but
decided to test it. I created a database with 2k tables like this:

CREATE TABLE test1990 (x SERIAL);

Running the git version of pg_upgrade on that took 203 seconds. Using
synchronous_commit=off dropped the time to 78 seconds. This was tested
on magnetic disks with a write-through cache. (No change on an SSD with
a super-capacitor.)

I don't see anything unsafe about having pg_upgrade use
synchronous_commit=off. I could set it just for the pg_dump reload, but
it seems safe to just use it always. We don't write to the old cluster,
and if pg_upgrade fails, you have to re-initdb the new cluster anyway.

Patch attached. I think it should be applied to 9.2 as well.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

Attachments:

sync_off.difftext/x-diff; charset=us-asciiDownload+5-5
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#1)
Re: Pg_upgrade speed for many tables

Bruce Momjian <bruce@momjian.us> writes:

Magnus reported that a customer with a million tables was finding
pg_upgrade slow.

You sure there's not an O(N^2) issue in there somewhere?

I don't see anything unsafe about having pg_upgrade use
synchronous_commit=off.

No objection, but this seems unlikely to be better than linear speedup,
with a not-terribly-large constant factor.

BTW, does pg_upgrade run pg_restore in --single-transaction mode?
That would probably make synchronous_commit moot, at least for that
step.

regards, tom lane

#3Magnus Hagander
magnus@hagander.net
In reply to: Tom Lane (#2)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 9:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Bruce Momjian <bruce@momjian.us> writes:

Magnus reported that a customer with a million tables was finding
pg_upgrade slow.

You sure there's not an O(N^2) issue in there somewhere?

I don't see anything unsafe about having pg_upgrade use
synchronous_commit=off.

No objection, but this seems unlikely to be better than linear speedup,
with a not-terribly-large constant factor.

BTW, does pg_upgrade run pg_restore in --single-transaction mode?
That would probably make synchronous_commit moot, at least for that
step.

It doesn't use pg_restore at all - it uses the dump from pg_dumpall, which
you can't reload with pg_restore.

--
Magnus Hagander
Me: http://www.hagander.net/
Work: http://www.redpill-linpro.com/

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Magnus Hagander (#3)
Re: Pg_upgrade speed for many tables

Magnus Hagander <magnus@hagander.net> writes:

On Mon, Nov 5, 2012 at 9:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

BTW, does pg_upgrade run pg_restore in --single-transaction mode?
That would probably make synchronous_commit moot, at least for that
step.

It doesn't use pg_restore at all - it uses the dump from pg_dumpall, which
you can't reload with pg_restore.

Sorry, I should've said psql --single-transaction. Although that isn't
going to work either given the presence of \connect commands in the
script. I wonder whether pg_dumpall ought to have some sort of "one
transaction per database please" option.

regards, tom lane

#5Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#4)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 03:30:32PM -0500, Tom Lane wrote:

Magnus Hagander <magnus@hagander.net> writes:

On Mon, Nov 5, 2012 at 9:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

BTW, does pg_upgrade run pg_restore in --single-transaction mode?
That would probably make synchronous_commit moot, at least for that
step.

It doesn't use pg_restore at all - it uses the dump from pg_dumpall, which
you can't reload with pg_restore.

Sorry, I should've said psql --single-transaction. Although that isn't
going to work either given the presence of \connect commands in the
script. I wonder whether pg_dumpall ought to have some sort of "one
transaction per database please" option.

pg_dumpall is already doing lots of gymnastics with SQL, and pg_upgrade
splits the output file into db/user creation and object creation, so I
am hesitant to add anything more in there.

I was surprised by the scale of the performance improvement, but a
simple table creation test confirmed that improvement, irregardless of
pg_upgrade. Perhaps we should suggest synchronous_commit=off for
pg_dumpall restores, particularly when using --schema-only.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

#6Magnus Hagander
magnus@hagander.net
In reply to: Bruce Momjian (#5)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 9:49 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Mon, Nov 5, 2012 at 03:30:32PM -0500, Tom Lane wrote:

Magnus Hagander <magnus@hagander.net> writes:

On Mon, Nov 5, 2012 at 9:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

BTW, does pg_upgrade run pg_restore in --single-transaction mode?
That would probably make synchronous_commit moot, at least for that
step.

It doesn't use pg_restore at all - it uses the dump from pg_dumpall,

which

you can't reload with pg_restore.

Sorry, I should've said psql --single-transaction. Although that isn't
going to work either given the presence of \connect commands in the
script. I wonder whether pg_dumpall ought to have some sort of "one
transaction per database please" option.

pg_dumpall is already doing lots of gymnastics with SQL, and pg_upgrade
splits the output file into db/user creation and object creation, so I
am hesitant to add anything more in there.

What about running pg_dump in a loop instead of pg_dumpall?

--
Magnus Hagander
Me: http://www.hagander.net/
Work: http://www.redpill-linpro.com/

#7Bruce Momjian
bruce@momjian.us
In reply to: Magnus Hagander (#6)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 10:01:22PM +0100, Magnus Hagander wrote:

On Mon, Nov 5, 2012 at 9:49 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Mon, Nov 5, 2012 at 03:30:32PM -0500, Tom Lane wrote:

Magnus Hagander <magnus@hagander.net> writes:

On Mon, Nov 5, 2012 at 9:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

BTW, does pg_upgrade run pg_restore in --single-transaction mode?
That would probably make synchronous_commit moot, at least for that
step.

It doesn't use pg_restore at all - it uses the dump from pg_dumpall,

which

you can't reload with pg_restore.

Sorry, I should've said psql --single-transaction. Although that isn't
going to work either given the presence of \connect commands in the
script. I wonder whether pg_dumpall ought to have some sort of "one
transaction per database please" option.

pg_dumpall is already doing lots of gymnastics with SQL, and pg_upgrade
splits the output file into db/user creation and object creation, so I
am hesitant to add anything more in there.

What about running pg_dump in a loop instead of pg_dumpall?

Well, I could cetainly do pg_dumpall --globals-only, and then I have to
create a pg_dump file for every database, and then add the \connect in
there; it just seemed easier to use pg_dumpall, though the file split
thing is certainly something I would like to get rid of.

I think I used pg_dumpall because it was an existing tool that I assumed
would be maintained to dump a full cluster.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

#8Jeff Janes
jeff.janes@gmail.com
In reply to: Bruce Momjian (#5)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 12:49 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Mon, Nov 5, 2012 at 03:30:32PM -0500, Tom Lane wrote:

Magnus Hagander <magnus@hagander.net> writes:

On Mon, Nov 5, 2012 at 9:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

BTW, does pg_upgrade run pg_restore in --single-transaction mode?
That would probably make synchronous_commit moot, at least for that
step.

It doesn't use pg_restore at all - it uses the dump from pg_dumpall, which
you can't reload with pg_restore.

Sorry, I should've said psql --single-transaction. Although that isn't
going to work either given the presence of \connect commands in the
script. I wonder whether pg_dumpall ought to have some sort of "one
transaction per database please" option.

pg_dumpall is already doing lots of gymnastics with SQL, and pg_upgrade
splits the output file into db/user creation and object creation, so I
am hesitant to add anything more in there.

I was surprised by the scale of the performance improvement, but a
simple table creation test confirmed that improvement, irregardless of
pg_upgrade. Perhaps we should suggest synchronous_commit=off for
pg_dumpall restores, particularly when using --schema-only.

Or have options for pg_dump and pg_restore to insert "set
synchronous_commit=off" into the SQL stream?

Cheers,

Jeff

#9Bruce Momjian
bruce@momjian.us
In reply to: Jeff Janes (#8)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 01:07:45PM -0800, Jeff Janes wrote:

On Mon, Nov 5, 2012 at 12:49 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Mon, Nov 5, 2012 at 03:30:32PM -0500, Tom Lane wrote:

Magnus Hagander <magnus@hagander.net> writes:

On Mon, Nov 5, 2012 at 9:14 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

BTW, does pg_upgrade run pg_restore in --single-transaction mode?
That would probably make synchronous_commit moot, at least for that
step.

It doesn't use pg_restore at all - it uses the dump from pg_dumpall, which
you can't reload with pg_restore.

Sorry, I should've said psql --single-transaction. Although that isn't
going to work either given the presence of \connect commands in the
script. I wonder whether pg_dumpall ought to have some sort of "one
transaction per database please" option.

pg_dumpall is already doing lots of gymnastics with SQL, and pg_upgrade
splits the output file into db/user creation and object creation, so I
am hesitant to add anything more in there.

I was surprised by the scale of the performance improvement, but a
simple table creation test confirmed that improvement, irregardless of
pg_upgrade. Perhaps we should suggest synchronous_commit=off for
pg_dumpall restores, particularly when using --schema-only.

Or have options for pg_dump and pg_restore to insert "set
synchronous_commit=off" into the SQL stream?

You can already do that with PGOPTIONS:

PGOPTIONS="-c synchronous_commit=off" pg_restore ...

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

#10Robert Haas
robertmhaas@gmail.com
In reply to: Jeff Janes (#8)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 4:07 PM, Jeff Janes <jeff.janes@gmail.com> wrote:

Or have options for pg_dump and pg_restore to insert "set
synchronous_commit=off" into the SQL stream?

It would be kind of neat if we had a command that would force all
previously-asynchronous commits to complete. It seems likely that
very, very few people would care about intermediate pg_dump states, so
we could do the whole dump asynchronously and then do "FORCE ALL
COMMITS;" or whatever at the end.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#11Bruce Momjian
bruce@momjian.us
In reply to: Robert Haas (#10)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 04:14:47PM -0500, Robert Haas wrote:

On Mon, Nov 5, 2012 at 4:07 PM, Jeff Janes <jeff.janes@gmail.com> wrote:

Or have options for pg_dump and pg_restore to insert "set
synchronous_commit=off" into the SQL stream?

It would be kind of neat if we had a command that would force all
previously-asynchronous commits to complete. It seems likely that
very, very few people would care about intermediate pg_dump states, so
we could do the whole dump asynchronously and then do "FORCE ALL
COMMITS;" or whatever at the end.

Actually, I had assumed that a session disconnection forced a WAL fsync
flush, but now I doubt that. Seems only server shutdown does that, or a
checkpoint. Would this work?

SET synchronous_commit=on;
CREATE TABLE dummy(x int);
DROP TABLE dummy;

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

#12Jeff Janes
jeff.janes@gmail.com
In reply to: Robert Haas (#10)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 1:14 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Mon, Nov 5, 2012 at 4:07 PM, Jeff Janes <jeff.janes@gmail.com> wrote:

Or have options for pg_dump and pg_restore to insert "set
synchronous_commit=off" into the SQL stream?

It would be kind of neat if we had a command that would force all
previously-asynchronous commits to complete. It seems likely that
very, very few people would care about intermediate pg_dump states, so
we could do the whole dump asynchronously and then do "FORCE ALL
COMMITS;" or whatever at the end.

Yeah, I was wondering what a fool-proof way of doing that would be,
without implementing a new feature. Turning synchronous_commits back
on and then doing and committing a transaction guaranteed to generate
WAL would do it.

Would a simple 'select pg_switch_xlog();' always accomplish the desired flush?

Cheers,

Jeff

#13Bruce Momjian
bruce@momjian.us
In reply to: Jeff Janes (#12)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 01:23:58PM -0800, Jeff Janes wrote:

On Mon, Nov 5, 2012 at 1:14 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Mon, Nov 5, 2012 at 4:07 PM, Jeff Janes <jeff.janes@gmail.com> wrote:

Or have options for pg_dump and pg_restore to insert "set
synchronous_commit=off" into the SQL stream?

It would be kind of neat if we had a command that would force all
previously-asynchronous commits to complete. It seems likely that
very, very few people would care about intermediate pg_dump states, so
we could do the whole dump asynchronously and then do "FORCE ALL
COMMITS;" or whatever at the end.

Yeah, I was wondering what a fool-proof way of doing that would be,
without implementing a new feature. Turning synchronous_commits back
on and then doing and committing a transaction guaranteed to generate
WAL would do it.

Would a simple 'select pg_switch_xlog();' always accomplish the desired flush?

That could generate a lot of WAL files if used regularly. :-( Does
SELECT txid_current() generate WAL? I think it does.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

#14Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Bruce Momjian (#11)
Re: Pg_upgrade speed for many tables

Bruce Momjian escribió:

On Mon, Nov 5, 2012 at 04:14:47PM -0500, Robert Haas wrote:

On Mon, Nov 5, 2012 at 4:07 PM, Jeff Janes <jeff.janes@gmail.com> wrote:

Or have options for pg_dump and pg_restore to insert "set
synchronous_commit=off" into the SQL stream?

It would be kind of neat if we had a command that would force all
previously-asynchronous commits to complete. It seems likely that
very, very few people would care about intermediate pg_dump states, so
we could do the whole dump asynchronously and then do "FORCE ALL
COMMITS;" or whatever at the end.

Actually, I had assumed that a session disconnection forced a WAL fsync
flush, but now I doubt that. Seems only server shutdown does that, or a
checkpoint. Would this work?

SET synchronous_commit=on;
CREATE TABLE dummy(x int);
DROP TABLE dummy;

AFAIR any transaction that modifies catalogs gets sync commit forcibly,
regardless of the setting. And sync commit means you get to wait for
all previous transactions to be flushed as well. So simply creating a
temp table ought to do the trick ...

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

#15Bruce Momjian
bruce@momjian.us
In reply to: Alvaro Herrera (#14)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 06:33:16PM -0300, Alvaro Herrera wrote:

Bruce Momjian escribi�:

On Mon, Nov 5, 2012 at 04:14:47PM -0500, Robert Haas wrote:

On Mon, Nov 5, 2012 at 4:07 PM, Jeff Janes <jeff.janes@gmail.com> wrote:

Or have options for pg_dump and pg_restore to insert "set
synchronous_commit=off" into the SQL stream?

It would be kind of neat if we had a command that would force all
previously-asynchronous commits to complete. It seems likely that
very, very few people would care about intermediate pg_dump states, so
we could do the whole dump asynchronously and then do "FORCE ALL
COMMITS;" or whatever at the end.

Actually, I had assumed that a session disconnection forced a WAL fsync
flush, but now I doubt that. Seems only server shutdown does that, or a
checkpoint. Would this work?

SET synchronous_commit=on;
CREATE TABLE dummy(x int);
DROP TABLE dummy;

AFAIR any transaction that modifies catalogs gets sync commit forcibly,
regardless of the setting. And sync commit means you get to wait for

Uh, I am not seeing that my testing because I was only doing CREATE
TABLE and it was affected by the synchronous_commit value.

all previous transactions to be flushed as well. So simply creating a
temp table ought to do the trick ...

I don't think TEMP tables write to WAL, for performance reasons.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

#16Robert Haas
robertmhaas@gmail.com
In reply to: Alvaro Herrera (#14)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 4:33 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

AFAIR any transaction that modifies catalogs gets sync commit forcibly,
regardless of the setting. And sync commit means you get to wait for
all previous transactions to be flushed as well. So simply creating a
temp table ought to do the trick ...

I don't think there's a carve-out for system tables ... but creating a
temp table with synchronous_commit=on will certainly do the trick.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#17Bruce Momjian
bruce@momjian.us
In reply to: Robert Haas (#16)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 04:39:27PM -0500, Robert Haas wrote:

On Mon, Nov 5, 2012 at 4:33 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

AFAIR any transaction that modifies catalogs gets sync commit forcibly,
regardless of the setting. And sync commit means you get to wait for
all previous transactions to be flushed as well. So simply creating a
temp table ought to do the trick ...

I don't think there's a carve-out for system tables ... but creating a
temp table with synchronous_commit=on will certainly do the trick.

What is a temp table writing to WAL? The pg_class/pg_attribute changes?

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +

#18Robert Haas
robertmhaas@gmail.com
In reply to: Bruce Momjian (#17)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 4:42 PM, Bruce Momjian <bruce@momjian.us> wrote:

On Mon, Nov 5, 2012 at 04:39:27PM -0500, Robert Haas wrote:

On Mon, Nov 5, 2012 at 4:33 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

AFAIR any transaction that modifies catalogs gets sync commit forcibly,
regardless of the setting. And sync commit means you get to wait for
all previous transactions to be flushed as well. So simply creating a
temp table ought to do the trick ...

I don't think there's a carve-out for system tables ... but creating a
temp table with synchronous_commit=on will certainly do the trick.

What is a temp table writing to WAL? The pg_class/pg_attribute changes?

Yes.

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

#19Andres Freund
andres@anarazel.de
In reply to: Bruce Momjian (#17)
Re: Pg_upgrade speed for many tables

On Mon, Nov 05, 2012 at 04:42:56PM -0500, Bruce Momjian wrote:

On Mon, Nov 5, 2012 at 04:39:27PM -0500, Robert Haas wrote:

On Mon, Nov 5, 2012 at 4:33 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

AFAIR any transaction that modifies catalogs gets sync commit forcibly,
regardless of the setting. And sync commit means you get to wait for
all previous transactions to be flushed as well. So simply creating a
temp table ought to do the trick ...

SET synchronous_commit = on;
SELECT txid_current();

Should be enough.

I don't think there's a carve-out for system tables ... but creating a
temp table with synchronous_commit=on will certainly do the trick.

What is a temp table writing to WAL? The pg_class/pg_attribute changes?

Yes.

Andres

#20Jeff Janes
jeff.janes@gmail.com
In reply to: Robert Haas (#16)
Re: Pg_upgrade speed for many tables

On Mon, Nov 5, 2012 at 1:39 PM, Robert Haas <robertmhaas@gmail.com> wrote:

On Mon, Nov 5, 2012 at 4:33 PM, Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

AFAIR any transaction that modifies catalogs gets sync commit forcibly,
regardless of the setting. And sync commit means you get to wait for
all previous transactions to be flushed as well. So simply creating a
temp table ought to do the trick ...

I don't think there's a carve-out for system tables ... but creating a
temp table with synchronous_commit=on will certainly do the trick.

But that seems like something that might be optimized away in the
future (for example, so that temp tables can be used on hot standbys)
resulting in action-at-a-distance breakage.

Is txid_current() more fundamental, i.e. less likely to change?

Cheers,

Jeff

#21Jeff Janes
jeff.janes@gmail.com
In reply to: Tom Lane (#2)
#22Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#13)
#23Josh Berkus
josh@agliodbs.com
In reply to: Tom Lane (#4)
#24Bruce Momjian
bruce@momjian.us
In reply to: Josh Berkus (#23)
#25Andrew Dunstan
andrew@dunslane.net
In reply to: Bruce Momjian (#24)
#26Bruce Momjian
bruce@momjian.us
In reply to: Bruce Momjian (#1)
#27Jeff Janes
jeff.janes@gmail.com
In reply to: Bruce Momjian (#1)
#28Jeff Davis
pgsql@j-davis.com
In reply to: Jeff Janes (#27)
#29Bruce Momjian
bruce@momjian.us
In reply to: Jeff Janes (#27)
#30Jeff Janes
jeff.janes@gmail.com
In reply to: Bruce Momjian (#29)
#31Bruce Momjian
bruce@momjian.us
In reply to: Jeff Janes (#30)
#32Jeff Janes
jeff.janes@gmail.com
In reply to: Bruce Momjian (#31)
#33Bruce Momjian
bruce@momjian.us
In reply to: Jeff Janes (#32)
#34Bruce Momjian
bruce@momjian.us
In reply to: Bruce Momjian (#33)
#35Bruce Momjian
bruce@momjian.us
In reply to: Bruce Momjian (#34)