On Tue, 2007-02-20 at 14:38 -0300, Alvaro Herrera wrote:
> Cool. I noticed that the SGML seems broken here:
Corrected.
> You need to close the <listitem> and <para> opened in the COPY mention.
>
> > +
> > + static void
> > + heap_sync_relation(Relation rel)
> > + {
> > + if (!rel->rd_istemp)
>
> No comment in this function?
I've added more comments as you suggest.
Thanks for the review.
--
Simon Riggs
EnterpriseDB http://www.enterprisedb.com
Index: doc/src/sgml/perform.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/perform.sgml,v
retrieving revision 1.63
diff -c -r1.63 perform.sgml
*** doc/src/sgml/perform.sgml 1 Feb 2007 19:10:24 -0000 1.63
--- doc/src/sgml/perform.sgml 22 Feb 2007 11:50:58 -0000
***************
*** 908,919 ****
will perform more slowly when <varname>archive_command</varname>
is set, as a result of their needing to write large amounts of WAL.
This applies to the following commands:
! <command>CREATE TABLE AS SELECT</command>,
! <command>CREATE INDEX</command> and also <command>COPY</command>, when
! it is executed in the same transaction as a prior
! <command>CREATE TABLE</command> or <command>TRUNCATE</command> command.
! </para>
!
</sect2>
<sect2 id="populate-analyze">
--- 908,928 ----
will perform more slowly when <varname>archive_command</varname>
is set, as a result of their needing to write large amounts of WAL.
This applies to the following commands:
! <itemizedlist>
! <listitem><para><command>CREATE TABLE AS SELECT</command></para></listitem>
! <listitem><para><command>CREATE INDEX</command></para></listitem>
! <listitem><para><command>ALTER TABLE SET TABLESPACE</command></para></listitem>
! <listitem><para><command>CLUSTER</command></para></listitem>
! <listitem>
! <para><command>COPY</command>, when it is executed after one of
! these commands, yet in the same transaction:
! <itemizedlist>
! <listitem><para><command>CREATE TABLE</command></para></listitem>
! <listitem><para><command>TRUNCATE</command></para></listitem>
! </itemizedlist>
! </para>
! </listitem>
! </itemizedlist>
</sect2>
<sect2 id="populate-analyze">
***************
*** 950,964 ****
By default, <application>pg_dump</> uses <command>COPY</>, and when
it is generating a complete schema-and-data dump, it is careful to
load data before creating indexes and foreign keys. So in this case
! the first several guidelines are handled automatically. What is left
! for you to do is to set appropriate (i.e., larger than normal) values
! for <varname>maintenance_work_mem</varname> and
! <varname>checkpoint_segments</varname>, as well as unsetting
! <varname>archive_command</varname> before loading the dump script,
! and then to run <command>ANALYZE</> afterwards and resetting
! <varname>archive_command</varname> if required. All of the
! parameters can be reset once the load has completed without needing
! to restart the server, as described in <xref linkend="config-setting">.
</para>
<para>
--- 959,992 ----
By default, <application>pg_dump</> uses <command>COPY</>, and when
it is generating a complete schema-and-data dump, it is careful to
load data before creating indexes and foreign keys. So in this case
! several guidelines are handled automatically. What is left
! for you to do is to:
! <itemizedlist>
! <listitem><para>Set appropriate (i.e., larger than normal) values
! for <varname>maintenance_work_mem</varname> and
! <varname>checkpoint_segments</varname>.</para></listitem>
! <listitem><para>Unset <varname>archive_command</varname> before
! loading the dump script, and then reset
! <varname>archive_command</varname> afterwards, if required.</para>
! </listitem>
! <listitem>
! <para>
! Consider whether the whole dump can be restored as a single
! transaction, so that COPY commands can be optimized. Remember that
! this will mean that all restore commands will either fully completed
! or fully rolled back. This mode can be specified by passing the
! <option>-1</> or <option>--single-transaction</> command-line options
! to <application>psql</> or <application>pg_restore</>. When using this
! mode, be aware that even the smallest of errors can rollback a
! restore that has already run for many hours. However, that might
! still be preferable to manually cleaning up a complex database
! after a partially restored dump.
! </para>
! </listitem>
! <listitem><para>Run <command>ANALYZE</> afterwards.</para></listitem>
! All of the above mentioned parameters can be reset once the load has
! completed without needing to restart the server, as described in
! <xref linkend="config-setting">.
</para>
<para>
Index: src/backend/access/heap/heapam.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/heap/heapam.c,v
retrieving revision 1.228
diff -c -r1.228 heapam.c
*** src/backend/access/heap/heapam.c 9 Feb 2007 03:35:33 -0000 1.228
--- src/backend/access/heap/heapam.c 22 Feb 2007 11:51:00 -0000
***************
*** 60,65 ****
--- 60,66 ----
static XLogRecPtr log_heap_update(Relation reln, Buffer oldbuf,
ItemPointerData from, Buffer newbuf, HeapTuple newtup, bool move);
+ static void heap_sync_relation(Relation rel);
/* ----------------------------------------------------------------
***************
*** 3991,3996 ****
--- 3992,4003 ----
/* ----------------
* heap_sync - sync a heap, for use when no WAL has been written
*
+ * Will sync all relations associated with the main table,
+ * i.e. the main heap, indexes, the toast relation and its index
+ * If new relation types were added, this would need extension
+ * XXX Indexes are mentioned because its possible in the future that
+ * we may choose to avoid writing WAL for indexes as well,
+ * in certain cicrumstances.
* ----------------
*/
void
***************
*** 3998,4003 ****
--- 4005,4042 ----
{
if (!rel->rd_istemp)
{
+ /* main heap */
+ heap_sync_relation(rel);
+
+ /* main heap indexes, if any */
+ /* we always use WAL for index inserts, so no need to sync */
+
+ /* toast heap, if any */
+ if (OidIsValid(rel->rd_rel->reltoastrelid))
+ {
+ Relation toastrel;
+
+ toastrel = heap_open(rel->rd_rel->reltoastrelid,
+ AccessShareLock);
+ heap_sync_relation(toastrel);
+ heap_close(toastrel, AccessShareLock);
+ }
+
+ /* toast index, if toast heap */
+ /* we always use WAL for index inserts, so no need to sync */
+ }
+ }
+
+ /*
+ * heap_sync_relation
+ *
+ * Worker function for heap_sync(). Performs sync for an individual relation.
+ */
+ static void
+ heap_sync_relation(Relation rel)
+ {
+ if (!rel->rd_istemp)
+ {
/*
* If we skipped using WAL, and it's not a temp relation,
* we must force the relation down to disk before it's
Index: src/backend/commands/cluster.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/cluster.c,v
retrieving revision 1.156
diff -c -r1.156 cluster.c
*** src/backend/commands/cluster.c 1 Feb 2007 19:10:25 -0000 1.156
--- src/backend/commands/cluster.c 22 Feb 2007 11:51:00 -0000
***************
*** 653,658 ****
--- 653,659 ----
char *nulls;
IndexScanDesc scan;
HeapTuple tuple;
+ bool use_wal;
/*
* Open the relations we need.
***************
*** 676,681 ****
--- 677,688 ----
memset(nulls, 'n', natts * sizeof(char));
/*
+ * We need to log the copied data in WAL iff WAL archiving is enabled AND
+ * it's not a temp rel.
+ */
+ use_wal = XLogArchivingActive() && !NewHeap->rd_istemp;
+
+ /*
* Scan through the OldHeap on the OldIndex and copy each tuple into the
* NewHeap.
*/
***************
*** 722,728 ****
if (NewHeap->rd_rel->relhasoids)
HeapTupleSetOid(copiedTuple, HeapTupleGetOid(tuple));
! simple_heap_insert(NewHeap, copiedTuple);
heap_freetuple(copiedTuple);
--- 729,735 ----
if (NewHeap->rd_rel->relhasoids)
HeapTupleSetOid(copiedTuple, HeapTupleGetOid(tuple));
! fast_heap_insert(NewHeap, copiedTuple, use_wal);
heap_freetuple(copiedTuple);
***************
*** 736,741 ****
--- 743,752 ----
index_close(OldIndex, NoLock);
heap_close(OldHeap, NoLock);
+
+ if (!use_wal)
+ heap_sync(NewHeap);
+
heap_close(NewHeap, NoLock);
}
Index: src/backend/commands/copy.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/copy.c,v
retrieving revision 1.276
diff -c -r1.276 copy.c
*** src/backend/commands/copy.c 20 Feb 2007 17:32:13 -0000 1.276
--- src/backend/commands/copy.c 22 Feb 2007 11:51:01 -0000
***************
*** 1857,1863 ****
* do not need to worry about inconsistent states.
* As mentioned in comments in utils/rel.h, the in-same-transaction test is
* not completely reliable, since rd_createSubId can be reset to zero in
! * certain cases before the end of the creating transaction.
* We are doing this for performance only, so we only need to know:
* if rd_createSubid != InvalidSubTransactionId then it is *always* just
* created. If we have PITR enabled, then we *must* use_wal
--- 1857,1865 ----
* do not need to worry about inconsistent states.
* As mentioned in comments in utils/rel.h, the in-same-transaction test is
* not completely reliable, since rd_createSubId can be reset to zero in
! * certain cases before the end of the creating transaction.
! * CLUSTER creates a new relfilenode but it removes the old one immediately
! * for other reasons, so we cannot optimise COPY following CLUSTER.
* We are doing this for performance only, so we only need to know:
* if rd_createSubid != InvalidSubTransactionId then it is *always* just
* created. If we have PITR enabled, then we *must* use_wal
***************
*** 2121,2148 ****
* If we skipped writing WAL for heaps, then we need to sync
*/
if (!use_wal)
- {
- /* main heap */
heap_sync(cstate->rel);
- /* main heap indexes, if any */
- /* we always use WAL for index inserts, so no need to sync */
-
- /* toast heap, if any */
- if (OidIsValid(cstate->rel->rd_rel->reltoastrelid))
- {
- Relation toastrel;
-
- toastrel = heap_open(cstate->rel->rd_rel->reltoastrelid,
- AccessShareLock);
- heap_sync(toastrel);
- heap_close(toastrel, AccessShareLock);
- }
-
- /* toast index, if toast heap */
- /* we always use WAL for index inserts, so no need to sync */
- }
-
/* Done, clean up */
error_context_stack = errcontext.previous;
--- 2123,2130 ----
---------------------------(end of broadcast)---------------------------
TIP 5: don't forget to increase your free space map settings