MemoryContext SPIcontext;
/* initialize our tuplestore */
- tupstore = tuplestore_begin_heap(true, false, SortMem);
+ tupstore = tuplestore_begin_heap(true, false, work_mem);
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
oldcontext = MemoryContextSwitchTo(per_query_ctx);
/* initialize our tuplestore */
- tupstore = tuplestore_begin_heap(true, false, SortMem);
+ tupstore = tuplestore_begin_heap(true, false, work_mem);
MemoryContextSwitchTo(oldcontext);
<!--
-$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.34 2004/01/19 20:12:30 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.35 2004/02/03 17:34:02 tgl Exp $
-->
<chapter id="backup">
<title>Backup and Restore</title>
<tip>
<para>
Restore performance can be improved by increasing the
- configuration parameter <varname>sort_mem</varname> (see <xref
- linkend="runtime-config-resource-memory">).
+ configuration parameter <varname>maintenance_work_mem</varname>
+ (see <xref linkend="runtime-config-resource-memory">).
</para>
</tip>
</sect2>
-<!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.193 2004/01/19 21:20:06 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/installation.sgml,v 1.194 2004/02/03 17:34:02 tgl Exp $ -->
<chapter id="installation">
<title><![%standalone-include[<productname>PostgreSQL</>]]>
not designed for optimum performance. To achieve optimum
performance, several server parameters must be adjusted, the two
most common being <varname>shared_buffers</varname> and
- <varname> sort_mem</varname> mentioned in the documentation.
+ <varname>work_mem</varname>.
Other parameters mentioned in the documentation also affect
performance.
</para>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/perform.sgml,v 1.40 2004/01/11 05:46:58 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/perform.sgml,v 1.41 2004/02/03 17:34:02 tgl Exp $
-->
<chapter id="performance-tips">
</para>
</sect2>
- <sect2 id="populate-sort-mem">
- <title>Increase <varname>sort_mem</varname></title>
+ <sect2 id="populate-work-mem">
+ <title>Increase <varname>maintenance_work_mem</varname></title>
<para>
- Temporarily increasing the <varname>sort_mem</varname>
+ Temporarily increasing the <varname>maintenance_work_mem</varname>
configuration variable when restoring large amounts of data can
lead to improved performance. This is because when a B-tree index
is created from scratch, the existing content of the table needs
- to be sorted. Allowing the merge sort to use more buffer pages
- means that fewer merge passes will be required.
+ to be sorted. Allowing the merge sort to use more memory
+ means that fewer merge passes will be required. A larger setting for
+ <varname>maintenance_work_mem</varname> may also speed up validation
+ of foreign-key constraints.
</para>
</sect2>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.34 2004/01/24 22:05:08 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.35 2004/02/03 17:34:02 tgl Exp $
-->
<chapter id="plpgsql">
allow users to define set-returning functions
that do not have this limitation. Currently, the point at
which data begins being written to disk is controlled by the
- <varname>sort_mem</> configuration variable. Administrators
+ <varname>work_mem</> configuration variable. Administrators
who have sufficient memory to store larger result sets in
memory should consider increasing this parameter.
</para>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/postgres-ref.sgml,v 1.42 2003/11/29 19:51:39 pgsql Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/postgres-ref.sgml,v 1.43 2004/02/03 17:34:02 tgl Exp $
PostgreSQL documentation
-->
<arg>-s</arg>
<arg>-t<group choice="plain"><arg>pa</arg><arg>pl</arg><arg>ex</arg></group></arg>
</group>
- <arg>-S <replaceable>sort-mem</replaceable></arg>
+ <arg>-S <replaceable>work-mem</replaceable></arg>
<arg>-W <replaceable>seconds</replaceable></arg>
<arg>--<replaceable>name</replaceable>=<replaceable>value</replaceable></arg>
<arg choice="plain"><replaceable>database</replaceable></arg>
<arg>-s</arg>
<arg>-t<group choice="plain"><arg>pa</arg><arg>pl</arg><arg>ex</arg></group></arg>
</group>
- <arg>-S <replaceable>sort-mem</replaceable></arg>
+ <arg>-S <replaceable>work-mem</replaceable></arg>
<arg>-v <replaceable>protocol</replaceable></arg>
<arg>-W <replaceable>seconds</replaceable></arg>
<arg>--<replaceable>name</replaceable>=<replaceable>value</replaceable></arg>
</varlistentry>
<varlistentry>
- <term><option>-S</option> <replaceable class="parameter">sort-mem</replaceable></term>
+ <term><option>-S</option> <replaceable class="parameter">work-mem</replaceable></term>
<listitem>
<para>
Specifies the amount of memory to be used by internal sorts and hashes
- before resorting to temporary disk files. The value is specified in
- kilobytes, and defaults to 1024. Note that for a complex query,
- several sorts and/or hashes might be running in parallel, and each one
- will be allowed to use as much as
- <replaceable class="parameter">sort-mem</replaceable> kilobytes
- before it starts to put data into temporary files.
+ before resorting to temporary disk files. See the description of the
+ <varname>work_mem</> configuration parameter in <xref
+ linkend="runtime-config-resource-memory">.
</para>
</listitem>
</varlistentry>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/postmaster.sgml,v 1.44 2003/12/14 00:15:03 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/postmaster.sgml,v 1.45 2004/02/03 17:34:02 tgl Exp $
PostgreSQL documentation
-->
<para>
Named run-time parameters can be set in either of these styles:
<screen>
-<prompt>$</prompt> <userinput>postmaster -c sort_mem=1234</userinput>
-<prompt>$</prompt> <userinput>postmaster --sort-mem=1234</userinput>
+<prompt>$</prompt> <userinput>postmaster -c work_mem=1234</userinput>
+<prompt>$</prompt> <userinput>postmaster --work-mem=1234</userinput>
</screen>
- Either form overrides whatever setting might exist for <varname>sort_mem</>
+ Either form overrides whatever setting might exist for <varname>work_mem</>
in <filename>postgresql.conf</>. Notice that underscores in parameter
names can be written as either underscore or dash on the command line.
</para>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.235 2004/01/27 16:51:43 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.236 2004/02/03 17:34:02 tgl Exp $
-->
<Chapter Id="runtime">
</varlistentry>
<varlistentry>
- <term><varname>sort_mem</varname> (<type>integer</type>)</term>
+ <term><varname>work_mem</varname> (<type>integer</type>)</term>
<listitem>
<para>
- Specifies the amount of memory to be used by internal sort operations and
- hash tables before switching to temporary disk files. The value is
+ Specifies the amount of memory to be used by internal sort operations
+ and hash tables before switching to temporary disk files. The value is
specified in kilobytes, and defaults to 1024 kilobytes (1 MB).
Note that for a complex query, several sort or hash operations might be
running in parallel; each one will be allowed to use as much memory
as this value specifies before it starts to put data into temporary
- files. Also, several running sessions could be doing
- sort operations simultaneously. So the total memory used could be many
- times the value of <varname>sort_mem</varname>. Sort operations are used
- by <literal>ORDER BY</>, merge joins, and <command>CREATE INDEX</>.
+ files. Also, several running sessions could be doing such operations
+ concurrently. So the total memory used could be many
+ times the value of <varname>work_mem</varname>; it is necessary to
+ keep this fact in mind when choosing the value. Sort operations are
+ used for <literal>ORDER BY</>, <literal>DISTINCT</>, and
+ merge joins.
Hash tables are used in hash joins, hash-based aggregation, and
- hash-based processing of <literal>IN</> subqueries. Because
- <command>CREATE INDEX</> is used when restoring a database,
- increasing <varname>sort_mem</varname> before doing a large
- restore operation can improve performance.
+ hash-based processing of <literal>IN</> subqueries.
</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><varname>vacuum_mem</varname> (<type>integer</type>)</term>
+ <term><varname>maintenance_work_mem</varname> (<type>integer</type>)</term>
<listitem>
<para>
- Specifies the maximum amount of memory to be used by
- <command>VACUUM</command> to keep track of to-be-reclaimed
- rows. The value is specified in kilobytes, and defaults to
- 8192 kB. Larger settings may improve the speed of
- vacuuming large tables that have many deleted rows.
+ Specifies the maximum amount of memory to be used in maintenance
+ operations, such as <command>VACUUM</command>, <command>CREATE
+ INDEX</>, and <command>ALTER TABLE ADD FOREIGN KEY</>.
+ The value is specified in kilobytes, and defaults to 16384 kilobytes
+ (16 MB). Since only one of these operations can be executed at
+ a time by a database session, and an installation normally doesn't
+ have very many of them happening concurrently, it's safe to set this
+ value significantly larger than <varname>work_mem</varname>. Larger
+ settings may improve performance for vacuuming and for restoring
+ database dumps.
</para>
</listitem>
</varlistentry>
<para>
Various tuning parameters for the genetic query optimization
algorithm. The recommended one to modify is
- <varname>geqo_effort</varname>, which can range from 1 to 10 with
- a default of 5. Larger values increase the time spent in planning
- but make it more likely that a good plan will be found.
- <varname>geqo_effort</varname> doesn't actually do anything directly,
- it is just used to compute the default values for the other
- parameters. If you prefer, you can set the other parameters by hand
- instead.
- The pool size is the number of individuals in the genetic population.
- It must be at least two, and useful values are typically 100 to 1000.
- If it is set to zero (the default setting) then a suitable default
- is chosen based on <varname>geqo_effort</varname> and the number of
- tables in the query.
- Generations specifies the number of iterations of the algorithm.
- It must be at least one, and useful values are in the same range
- as the pool size.
- If it is set to zero (the default setting) then a suitable default
- is chosen based on the pool size.
- The run time of the algorithm is roughly proportional to the sum of
- pool size and generations.
+ <varname>geqo_effort</varname>, which can range from 1 to 10 with
+ a default of 5. Larger values increase the time spent in planning
+ but make it more likely that a good plan will be found.
+ <varname>geqo_effort</varname> doesn't actually do anything directly,
+ it is just used to compute the default values for the other
+ parameters. If you prefer, you can set the other parameters by hand
+ instead.
+ The pool size is the number of individuals in the genetic population.
+ It must be at least two, and useful values are typically 100 to 1000.
+ If it is set to zero (the default setting) then a suitable default
+ is chosen based on <varname>geqo_effort</varname> and the number of
+ tables in the query.
+ Generations specifies the number of iterations of the algorithm.
+ It must be at least one, and useful values are in the same range
+ as the pool size.
+ If it is set to zero (the default setting) then a suitable default
+ is chosen based on the pool size.
+ The run time of the algorithm is roughly proportional to the sum of
+ pool size and generations.
The selection bias is the selective pressure within the
population. Values can be from 1.50 to 2.00; the latter is the
default.
<row>
<entry><option>-S <replaceable>x</replaceable></option><footnoteref linkend="fn.runtime-config-short">
</entry>
- <entry><literal>sort_mem = <replaceable>x</replaceable></></entry>
+ <entry><literal>work_mem = <replaceable>x</replaceable></></entry>
</row>
<row>
<para>
In OS X 10.2 and earlier, edit the file
<filename>/System/Library/StartupItems/SystemTuning/SystemTuning</>
- and change the values in the following commands:
+ and change the values in the following commands:
<programlisting>
sysctl -w kern.sysv.shmmax
sysctl -w kern.sysv.shmmin
sysctl -w kern.sysv.shmall
</programlisting>
In OS X 10.3, these commands have been moved to <filename>/etc/rc</>
- and must be edited there.
+ and must be edited there.
</para>
</listitem>
</varlistentry>
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.109 2004/01/07 18:56:24 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.110 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (buildstate.usefast)
{
- buildstate.spool = _bt_spoolinit(index, indexInfo->ii_Unique);
+ buildstate.spool = _bt_spoolinit(index, indexInfo->ii_Unique, false);
/*
- * Different from spool, the uniqueness isn't checked for spool2.
+ * If building a unique index, put dead tuples in a second spool
+ * to keep them out of the uniqueness check.
*/
if (indexInfo->ii_Unique)
- buildstate.spool2 = _bt_spoolinit(index, false);
+ buildstate.spool2 = _bt_spoolinit(index, false, true);
}
/* do the heap scan */
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.80 2004/01/07 18:56:24 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.81 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* create and initialize a spool structure
*/
BTSpool *
-_bt_spoolinit(Relation index, bool isunique)
+_bt_spoolinit(Relation index, bool isunique, bool isdead)
{
BTSpool *btspool = (BTSpool *) palloc0(sizeof(BTSpool));
+ int btKbytes;
btspool->index = index;
btspool->isunique = isunique;
- btspool->sortstate = tuplesort_begin_index(index, isunique, false);
+ /*
+ * We size the sort area as maintenance_work_mem rather than work_mem to
+ * speed index creation. This should be OK since a single backend can't
+ * run multiple index creations in parallel. Note that creation of a
+ * unique index actually requires two BTSpool objects. We expect that the
+ * second one (for dead tuples) won't get very full, so we give it only
+ * work_mem.
+ */
+ btKbytes = isdead ? work_mem : maintenance_work_mem;
+ btspool->sortstate = tuplesort_begin_index(index, isunique,
+ btKbytes, false);
/*
* Currently, tuplesort provides sort functions on IndexTuples. If we
* relations with finite memory space usage. To do that, we set upper bounds
* on the number of tuples and pages we will keep track of at once.
*
- * We are willing to use at most VacuumMem memory space to keep track of
- * dead tuples. We initially allocate an array of TIDs of that size.
- * If the array threatens to overflow, we suspend the heap scan phase
- * and perform a pass of index cleanup and page compaction, then resume
- * the heap scan with an empty TID array.
+ * We are willing to use at most maintenance_work_mem memory space to keep
+ * track of dead tuples. We initially allocate an array of TIDs of that size.
+ * If the array threatens to overflow, we suspend the heap scan phase and
+ * perform a pass of index cleanup and page compaction, then resume the heap
+ * scan with an empty TID array.
*
* We can limit the storage for page free space to MaxFSMPages entries,
* since that's the most the free space map will be willing to remember
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.33 2003/11/29 19:51:48 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.34 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int maxtuples;
int maxpages;
- maxtuples = (int) ((VacuumMem * 1024L) / sizeof(ItemPointerData));
- /* stay sane if small VacuumMem */
+ maxtuples = (int) ((maintenance_work_mem * 1024L) / sizeof(ItemPointerData));
+ /* stay sane if small maintenance_work_mem */
if (maxtuples < MAX_TUPLES_PER_PAGE)
maxtuples = MAX_TUPLES_PER_PAGE;
{
/*
* The array shouldn't overflow under normal behavior, but perhaps it
- * could if we are given a really small VacuumMem. In that case, just
- * forget the last few tuples.
+ * could if we are given a really small maintenance_work_mem. In that
+ * case, just forget the last few tuples.
*/
if (vacrelstats->num_dead_tuples < vacrelstats->max_dead_tuples)
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.153 2004/01/07 18:56:26 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.154 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
0,
false);
}
- tupstore = tuplestore_begin_heap(true, false, SortMem);
+ tupstore = tuplestore_begin_heap(true, false, work_mem);
MemoryContextSwitchTo(oldcontext);
rsinfo.setResult = tupstore;
rsinfo.setDesc = tupdesc;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.117 2003/11/29 19:51:48 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.118 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
peraggstate->sortstate =
tuplesort_begin_datum(peraggstate->inputType,
peraggstate->sortOperator,
- false);
+ work_mem, false);
}
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.81 2003/11/29 19:51:48 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.82 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
inner_rel_bytes = ntuples * tupsize * FUDGE_FAC;
/*
- * Target in-memory hashtable size is SortMem kilobytes.
+ * Target in-memory hashtable size is work_mem kilobytes.
*/
- hash_table_bytes = SortMem * 1024L;
+ hash_table_bytes = work_mem * 1024L;
/*
* Count the number of hash buckets we want for the whole relation,
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.90 2004/01/07 18:56:26 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.91 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* preferred way to do this is to record already-returned tuples in a hash
* table (using the TID as unique identifier). However, in a very large
* scan this could conceivably run out of memory. We limit the hash table
- * to no more than SortMem KB; if it grows past that, we fall back to the
+ * to no more than work_mem KB; if it grows past that, we fall back to the
* pre-7.4 technique: evaluate the prior-scan index quals again for each
* tuple (which is space-efficient, but slow).
*
HASHCTL hash_ctl;
long nbuckets;
- node->iss_MaxHash = (SortMem * 1024L) /
+ node->iss_MaxHash = (work_mem * 1024L) /
(MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(sizeof(DupHashTabEntry)));
MemSet(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = SizeOfIptrData;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.45 2003/11/29 19:51:48 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.46 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
if (tuplestorestate == NULL)
{
- tuplestorestate = tuplestore_begin_heap(true, false, SortMem);
+ tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
node->tuplestorestate = (void *) tuplestorestate;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeSort.c,v 1.46 2003/11/29 19:51:48 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeSort.c,v 1.47 2004/02/03 17:34:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "executor/execdebug.h"
#include "executor/nodeSort.h"
+#include "miscadmin.h"
#include "utils/tuplesort.h"
plannode->numCols,
plannode->sortOperators,
plannode->sortColIdx,
+ work_mem,
true /* randomAccess */ );
node->tuplesortstate = (void *) tuplesortstate;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.123 2004/01/19 03:52:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.124 2004/02/03 17:34:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* Determines and returns the cost of sorting a relation, including
* the cost of reading the input data.
*
- * If the total volume of data to sort is less than SortMem, we will do
+ * If the total volume of data to sort is less than work_mem, we will do
* an in-memory sort, which requires no I/O and about t*log2(t) tuple
* comparisons for t tuples.
*
- * If the total volume exceeds SortMem, we switch to a tape-style merge
+ * If the total volume exceeds work_mem, we switch to a tape-style merge
* algorithm. There will still be about t*log2(t) tuple comparisons in
* total, but we will also need to write and read each tuple once per
* merge pass. We expect about ceil(log6(r)) merge passes where r is the
* number of initial runs formed (log6 because tuplesort.c uses six-tape
- * merging). Since the average initial run should be about twice SortMem,
+ * merging). Since the average initial run should be about twice work_mem,
* we have
- * disk traffic = 2 * relsize * ceil(log6(p / (2*SortMem)))
+ * disk traffic = 2 * relsize * ceil(log6(p / (2*work_mem)))
* cpu = comparison_cost * t * log2(t)
*
* The disk traffic is assumed to be half sequential and half random
Cost startup_cost = input_cost;
Cost run_cost = 0;
double nbytes = relation_byte_size(tuples, width);
- long sortmembytes = SortMem * 1024L;
+ long work_mem_bytes = work_mem * 1024L;
if (!enable_sort)
startup_cost += disable_cost;
startup_cost += 2.0 * cpu_operator_cost * tuples * LOG2(tuples);
/* disk costs */
- if (nbytes > sortmembytes)
+ if (nbytes > work_mem_bytes)
{
double npages = ceil(nbytes / BLCKSZ);
- double nruns = nbytes / (sortmembytes * 2);
+ double nruns = nbytes / (work_mem_bytes * 2);
double log_runs = ceil(LOG6(nruns));
double npageaccesses;
* Determines and returns the cost of materializing a relation, including
* the cost of reading the input data.
*
- * If the total volume of data to materialize exceeds SortMem, we will need
+ * If the total volume of data to materialize exceeds work_mem, we will need
* to write it to disk, so the cost is much higher in that case.
*/
void
Cost startup_cost = input_cost;
Cost run_cost = 0;
double nbytes = relation_byte_size(tuples, width);
- long sortmembytes = SortMem * 1024L;
+ long work_mem_bytes = work_mem * 1024L;
/* disk costs */
- if (nbytes > sortmembytes)
+ if (nbytes > work_mem_bytes)
{
double npages = ceil(nbytes / BLCKSZ);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.165 2004/01/18 00:50:02 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.166 2004/02/03 17:34:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
/*
* Use hashed grouping if (a) we think we can fit the
- * hashtable into SortMem, *and* (b) the estimated cost is
+ * hashtable into work_mem, *and* (b) the estimated cost is
* no more than doing it the other way. While avoiding
* the need for sorted input is usually a win, the fact
* that the output won't be sorted may be a loss; so we
*/
int hashentrysize = cheapest_path_width + 64 + numAggs * 100;
- if (hashentrysize * dNumGroups <= SortMem * 1024L)
+ if (hashentrysize * dNumGroups <= work_mem * 1024L)
{
/*
* Okay, do the cost comparison. We need to consider
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.87 2004/01/12 22:20:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.88 2004/02/03 17:34:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
return false;
/*
- * The estimated size of the subquery result must fit in SortMem. (XXX
+ * The estimated size of the subquery result must fit in work_mem. (XXX
* what about hashtable overhead?)
*/
subquery_size = node->plan->plan_rows *
(MAXALIGN(node->plan->plan_width) + MAXALIGN(sizeof(HeapTupleData)));
- if (subquery_size > SortMem * 1024L)
+ if (subquery_size > work_mem * 1024L)
return false;
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.100 2004/01/19 03:49:41 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.101 2004/02/03 17:34:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
int hashentrysize = rel->width + 64;
- if (hashentrysize * pathnode->rows <= SortMem * 1024L)
+ if (hashentrysize * pathnode->rows <= work_mem * 1024L)
{
cost_agg(&agg_path, root,
AGG_HASHED, 0,
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.387 2004/01/28 21:02:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.388 2004/02/03 17:34:03 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
printf(gettext(" -o FILENAME send stdout and stderr to given file\n"));
printf(gettext(" -P disable system indexes\n"));
printf(gettext(" -s show statistics after each query\n"));
- printf(gettext(" -S SORT-MEM set amount of memory for sorts (in kbytes)\n"));
+ printf(gettext(" -S WORK-MEM set amount of memory for sorts (in kbytes)\n"));
printf(gettext(" --describe-config describe configuration parameters, then exit\n"));
printf(gettext(" --help show this help, then exit\n"));
printf(gettext(" --version output version information, then exit\n"));
/*
* S - amount of sort memory to use in 1k bytes
*/
- SetConfigOption("sort_mem", optarg, ctx, gucsource);
+ SetConfigOption("work_mem", optarg, ctx, gucsource);
break;
case 's':
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.66 2004/01/07 18:56:28 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.67 2004/02/03 17:34:03 tgl Exp $
*
* ----------
*/
#include "utils/lsyscache.h"
#include "utils/typcache.h"
#include "utils/acl.h"
+#include "utils/guc.h"
#include "miscadmin.h"
const char *sep;
List *list;
List *list2;
+ int old_work_mem;
+ char workmembuf[32];
int spi_result;
void *qplan;
snprintf(querystr + strlen(querystr), sizeof(querystr) - strlen(querystr),
")");
+ /*
+ * Temporarily increase work_mem so that the check query can be executed
+ * more efficiently. It seems okay to do this because the query is simple
+ * enough to not use a multiple of work_mem, and one typically would not
+ * have many large foreign-key validations happening concurrently. So
+ * this seems to meet the criteria for being considered a "maintenance"
+ * operation, and accordingly we use maintenance_work_mem.
+ *
+ * We do the equivalent of "SET LOCAL work_mem" so that transaction abort
+ * will restore the old value if we lose control due to an error.
+ */
+ old_work_mem = work_mem;
+ snprintf(workmembuf, sizeof(workmembuf), "%d", maintenance_work_mem);
+ (void) set_config_option("work_mem", workmembuf,
+ PGC_USERSET, PGC_S_SESSION,
+ true, true);
+
if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "SPI_connect failed");
if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "SPI_finish failed");
+ /*
+ * Restore work_mem for the remainder of the current transaction.
+ * This is another SET LOCAL, so it won't affect the session value,
+ * nor any tentative value if there is one.
+ */
+ snprintf(workmembuf, sizeof(workmembuf), "%d", old_work_mem);
+ (void) set_config_option("work_mem", workmembuf,
+ PGC_USERSET, PGC_S_SESSION,
+ true, true);
+
return true;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.81 2004/01/28 21:02:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.82 2004/02/03 17:34:03 tgl Exp $
*
* NOTES
* Globals used all over the place should be declared here and not
bool enableFsync = true;
bool allowSystemTableMods = false;
-int SortMem = 1024;
-int VacuumMem = 8192;
+int work_mem = 1024;
+int maintenance_work_mem = 16384;
int NBuffers = 1000;
* Written by Peter Eisentraut <peter_e@gmx.net>.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.183 2004/02/02 00:17:21 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.184 2004/02/03 17:34:03 tgl Exp $
*
*--------------------------------------------------------------------
*/
},
{
- {"sort_mem", PGC_USERSET, RESOURCES_MEM,
- gettext_noop("Sets the maximum memory to be used for sorts and hash tables."),
- gettext_noop("Specifies the amount of memory to be used by internal "
- "sort operations and hash tables before switching to temporary disk "
- "files")
+ {"work_mem", PGC_USERSET, RESOURCES_MEM,
+ gettext_noop("Sets the maximum memory to be used for query workspaces."),
+ gettext_noop("This much memory may be used by each internal "
+ "sort operation and hash table before switching to "
+ "temporary disk files.")
},
- &SortMem,
- 1024, 8 * BLCKSZ / 1024, INT_MAX, NULL, NULL
+ &work_mem,
+ 1024, 8 * BLCKSZ / 1024, INT_MAX / 1024, NULL, NULL
},
{
- {"vacuum_mem", PGC_USERSET, RESOURCES_MEM,
- gettext_noop("Sets the maximum memory used to keep track of to-be-reclaimed rows."),
- NULL
+ {"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
+ gettext_noop("Sets the maximum memory to be used for maintenance operations."),
+ gettext_noop("This includes operations such as VACUUM and CREATE INDEX.")
},
- &VacuumMem,
- 8192, 1024, INT_MAX, NULL, NULL
+ &maintenance_work_mem,
+ 16384, 1024, INT_MAX / 1024, NULL, NULL
},
{
/*
+ * To allow continued support of obsolete names for GUC variables, we apply
+ * the following mappings to any unrecognized name. Note that an old name
+ * should be mapped to a new one only if the new variable has very similar
+ * semantics to the old.
+ */
+static const char * const map_old_guc_names[] = {
+ "sort_mem", "work_mem",
+ "vacuum_mem", "maintenance_work_mem",
+ NULL
+};
+
+
+/*
* Actual lookup of variables is done through this single, sorted array.
*/
struct config_generic **guc_variables;
static int guc_var_compare(const void *a, const void *b);
+static int guc_name_compare(const char *namea, const char *nameb);
static void ReportGUCOption(struct config_generic * record);
static char *_ShowOption(struct config_generic * record);
{
const char **key = &name;
struct config_generic **res;
+ int i;
Assert(name);
/*
- * by equating const char ** with struct config_generic *, we are
+ * By equating const char ** with struct config_generic *, we are
* assuming the name field is first in config_generic.
*/
res = (struct config_generic **) bsearch((void *) &key,
guc_var_compare);
if (res)
return *res;
+
+ /*
+ * See if the name is an obsolete name for a variable. We assume that
+ * the set of supported old names is short enough that a brute-force
+ * search is the best way.
+ */
+ for (i = 0; map_old_guc_names[i] != NULL; i += 2)
+ {
+ if (guc_name_compare(name, map_old_guc_names[i]) == 0)
+ return find_option(map_old_guc_names[i+1]);
+ }
+
+ /* Unknown name */
return NULL;
}
{
struct config_generic *confa = *(struct config_generic **) a;
struct config_generic *confb = *(struct config_generic **) b;
- const char *namea;
- const char *nameb;
+ return guc_name_compare(confa->name, confb->name);
+}
+
+
+static int
+guc_name_compare(const char *namea, const char *nameb)
+{
/*
* The temptation to use strcasecmp() here must be resisted, because
* the array ordering has to remain stable across setlocale() calls.
* So, build our own with a simple ASCII-only downcasing.
*/
- namea = confa->name;
- nameb = confb->name;
while (*namea && *nameb)
{
char cha = *namea++;
# - Memory -
#shared_buffers = 1000 # min 16, at least max_connections*2, 8KB each
-#sort_mem = 1024 # min 64, size in KB
-#vacuum_mem = 8192 # min 1024, size in KB
+#work_mem = 1024 # min 64, size in KB
+#maintenance_work_mem = 16384 # min 1024, size in KB
#debug_shared_buffers = 0 # 0-600 seconds
# - Background writer -
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.63 2003/11/29 19:52:04 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.64 2004/02/03 17:34:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Create the tuple store, selecting cross-transaction temp files. */
oldcxt = MemoryContextSwitchTo(portal->holdContext);
- /* XXX: Should SortMem be used for this? */
- portal->holdStore = tuplestore_begin_heap(true, true, SortMem);
+ /* XXX: Should maintenance_work_mem be used for the portal size? */
+ portal->holdStore = tuplestore_begin_heap(true, true, work_mem);
MemoryContextSwitchTo(oldcxt);
}
* heap. When the run number at the top of the heap changes, we know that
* no more records of the prior run are left in the heap.
*
- * The (approximate) amount of memory allowed for any one sort operation
- * is given in kilobytes by the external variable SortMem. Initially,
+ * The approximate amount of memory allowed for any one sort operation
+ * is specified in kilobytes by the caller (most pass work_mem). Initially,
* we absorb tuples and simply store them in an unsorted array as long as
- * we haven't exceeded SortMem. If we reach the end of the input without
- * exceeding SortMem, we sort the array using qsort() and subsequently return
+ * we haven't exceeded workMem. If we reach the end of the input without
+ * exceeding workMem, we sort the array using qsort() and subsequently return
* tuples just by scanning the tuple array sequentially. If we do exceed
- * SortMem, we construct a heap using Algorithm H and begin to emit tuples
+ * workMem, we construct a heap using Algorithm H and begin to emit tuples
* into sorted runs in temporary tapes, emitting just enough tuples at each
- * step to get back within the SortMem limit. Whenever the run number at
+ * step to get back within the workMem limit. Whenever the run number at
* the top of the heap changes, we begin a new run with a new output tape
* (selected per Algorithm D). After the end of the input is reached,
* we dump out remaining tuples in memory into a final run (or two),
* next tuple from its source tape (if any). When the heap empties, the merge
* is complete. The basic merge algorithm thus needs very little memory ---
* only M tuples for an M-way merge, and M is at most six in the present code.
- * However, we can still make good use of our full SortMem allocation by
+ * However, we can still make good use of our full workMem allocation by
* pre-reading additional tuples from each source tape. Without prereading,
* our access pattern to the temporary file would be very erratic; on average
* we'd read one block from each of M source tapes during the same time that
* of the temp file, ensuring that things will be even worse when it comes
* time to read that tape. A straightforward merge pass thus ends up doing a
* lot of waiting for disk seeks. We can improve matters by prereading from
- * each source tape sequentially, loading about SortMem/M bytes from each tape
+ * each source tape sequentially, loading about workMem/M bytes from each tape
* in turn. Then we run the merge algorithm, writing but not reading until
* one of the preloaded tuple series runs out. Then we switch back to preread
* mode, fill memory again, and repeat. This approach helps to localize both
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.40 2003/11/29 19:52:04 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.41 2004/02/03 17:34:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*
* NOTES about memory consumption calculations:
*
- * We count space allocated for tuples against the SortMem limit, plus
+ * We count space allocated for tuples against the workMem limit, plus
* the space used by the variable-size arrays memtuples and memtupindex.
* Fixed-size space (primarily the LogicalTapeSet I/O buffers) is not
* counted.
} DatumTuple;
-static Tuplesortstate *tuplesort_begin_common(bool randomAccess);
+static Tuplesortstate *tuplesort_begin_common(int workMem, bool randomAccess);
static void puttuple_common(Tuplesortstate *state, void *tuple);
static void inittapes(Tuplesortstate *state);
static void selectnewtape(Tuplesortstate *state);
* access was requested, rescan, markpos, and restorepos can also be called.)
* For Datum sorts, putdatum/getdatum are used instead of puttuple/gettuple.
* Call tuplesort_end to terminate the operation and release memory/disk space.
+ *
+ * Each variant of tuplesort_begin has a workMem parameter specifying the
+ * maximum number of kilobytes of RAM to use before spilling data to disk.
+ * (The normal value of this parameter is work_mem, but some callers use
+ * other values.) Each variant also has a randomAccess parameter specifying
+ * whether the caller needs non-sequential access to the sort result.
*/
static Tuplesortstate *
-tuplesort_begin_common(bool randomAccess)
+tuplesort_begin_common(int workMem, bool randomAccess)
{
Tuplesortstate *state;
state->status = TSS_INITIAL;
state->randomAccess = randomAccess;
- state->availMem = SortMem * 1024L;
+ state->availMem = workMem * 1024L;
state->tapeset = NULL;
state->memtupcount = 0;
tuplesort_begin_heap(TupleDesc tupDesc,
int nkeys,
Oid *sortOperators, AttrNumber *attNums,
- bool randomAccess)
+ int workMem, bool randomAccess)
{
- Tuplesortstate *state = tuplesort_begin_common(randomAccess);
+ Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
int i;
AssertArg(nkeys > 0);
Tuplesortstate *
tuplesort_begin_index(Relation indexRel,
bool enforceUnique,
- bool randomAccess)
+ int workMem, bool randomAccess)
{
- Tuplesortstate *state = tuplesort_begin_common(randomAccess);
+ Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
state->comparetup = comparetup_index;
state->copytup = copytup_index;
Tuplesortstate *
tuplesort_begin_datum(Oid datumType,
Oid sortOperator,
- bool randomAccess)
+ int workMem, bool randomAccess)
{
- Tuplesortstate *state = tuplesort_begin_common(randomAccess);
+ Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess);
RegProcedure sortFunction;
int16 typlen;
bool typbyval;
/*
* If we produced only one initial run (quite likely if the total data
- * volume is between 1X and 2X SortMem), we can just use that tape as
+ * volume is between 1X and 2X workMem), we can just use that tape as
* the finished output, rather than doing a useless merge.
*/
if (state->currentRun == 1)
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.17 2003/11/29 19:52:04 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.18 2004/02/03 17:34:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
state->myfile = NULL;
state->memtupcount = 0;
- if (maxKBytes > 0)
- state->memtupsize = 1024; /* initial guess */
- else
- state->memtupsize = 1; /* won't really need any space */
+ state->memtupsize = 1024; /* initial guess */
state->memtuples = (void **) palloc(state->memtupsize * sizeof(void *));
USEMEM(state, GetMemoryChunkSpace(state->memtuples));
* no longer wanted.
*
* maxKBytes: how much data to store in memory (any data beyond this
- * amount is paged to disk).
+ * amount is paged to disk). When in doubt, use work_mem.
*/
Tuplestorestate *
tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
*
* Copyright (c) 2000-2003, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.100 2004/01/25 03:07:22 neilc Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.101 2004/02/03 17:34:03 tgl Exp $
*/
/*----------------------------------------------------------------------
"log_planner_stats",
"log_statement",
"log_statement_stats",
+ "maintenance_work_mem",
"max_connections",
"max_expr_depth",
"max_files_per_process",
"shared_buffers",
"seed",
"server_encoding",
- "sort_mem",
"sql_inheritance",
"ssl",
"statement_timeout",
"unix_socket_directory",
"unix_socket_group",
"unix_socket_permissions",
- "vacuum_mem",
"wal_buffers",
"wal_debug",
"wal_sync_method",
+ "work_mem",
NULL
};
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.75 2003/12/21 01:23:06 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.76 2004/02/03 17:34:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
typedef struct BTSpool BTSpool; /* opaque type known only within nbtsort.c */
-extern BTSpool *_bt_spoolinit(Relation index, bool isunique);
+extern BTSpool *_bt_spoolinit(Relation index, bool isunique, bool isdead);
extern void _bt_spooldestroy(BTSpool *btspool);
extern void _bt_spool(BTItem btitem, BTSpool *btspool);
extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2);
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.149 2004/01/30 15:57:04 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.150 2004/02/03 17:34:03 tgl Exp $
*
* NOTES
* some of the information in this file should be moved to
extern bool enableFsync;
extern bool allowSystemTableMods;
-extern DLLIMPORT int SortMem;
-extern int VacuumMem;
+extern DLLIMPORT int work_mem;
+extern DLLIMPORT int maintenance_work_mem;
/*
* A few postmaster startup options are exported here so the
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/tuplesort.h,v 1.14 2003/11/29 22:41:16 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/tuplesort.h,v 1.15 2004/02/03 17:34:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern Tuplesortstate *tuplesort_begin_heap(TupleDesc tupDesc,
int nkeys,
Oid *sortOperators, AttrNumber *attNums,
- bool randomAccess);
+ int workMem, bool randomAccess);
extern Tuplesortstate *tuplesort_begin_index(Relation indexRel,
bool enforceUnique,
- bool randomAccess);
+ int workMem, bool randomAccess);
extern Tuplesortstate *tuplesort_begin_datum(Oid datumType,
Oid sortOperator,
- bool randomAccess);
+ int workMem, bool randomAccess);
extern void tuplesort_puttuple(Tuplesortstate *state, void *tuple);
* procedural language
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.94 2003/11/29 19:52:12 pgsql Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.95 2004/02/03 17:34:04 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
estate->tuple_store_cxt = rsi->econtext->ecxt_per_query_memory;
oldcxt = MemoryContextSwitchTo(estate->tuple_store_cxt);
- estate->tuple_store = tuplestore_begin_heap(true, false, SortMem);
+ estate->tuple_store = tuplestore_begin_heap(true, false, work_mem);
MemoryContextSwitchTo(oldcxt);
estate->rettupdesc = rsi->expectedDesc;