Commit 8828689a authored by Tom Lane's avatar Tom Lane

Make an editorial pass over the newly SGML-ified contrib documentation.

Fix lots of bad markup, bad English, bad explanations.

Second round of commits.  pgcrypto and pgstandby still to go...
parent a3102ce1
<!-- $PostgreSQL: pgsql/doc/src/sgml/intagg.sgml,v 1.3 2007/12/10 05:32:51 tgl Exp $ -->
<sect1 id="intagg"> <sect1 id="intagg">
<title>intagg</title> <title>intagg</title>
<indexterm zone="intagg"> <indexterm zone="intagg">
<primary>intagg</primary> <primary>intagg</primary>
</indexterm> </indexterm>
<para> <para>
This section describes the <literal>intagg</literal> module which provides an integer aggregator and an enumerator. The <filename>intagg</filename> module provides an integer aggregator and an
enumerator.
</para>
<sect2>
<title>Functions</title>
<para>
The aggregator is an aggregate function
<function>int_array_aggregate(integer)</>
that produces an integer array
containing exactly the integers it is fed.
Here is a not-tremendously-useful example:
</para> </para>
<programlisting>
test=# select int_array_aggregate(i) from
test-# generate_series(1,10,2) i;
int_array_aggregate
---------------------
{1,3,5,7,9}
(1 row)
</programlisting>
<para> <para>
Many database systems have the notion of a one to many table. Such a table usually sits between two indexed tables, as: The enumerator is a function
<function>int_array_enum(integer[])</>
that returns <type>setof integer</>. It is essentially the reverse
operation of the aggregator: given an array of integers, expand it
into a set of rows. For example,
</para> </para>
<programlisting>
test=# select * from int_array_enum(array[1,3,5,7,9]);
int_array_enum
----------------
1
3
5
7
9
(5 rows)
</programlisting>
</sect2>
<sect2>
<title>Sample Uses</title>
<para>
Many database systems have the notion of a one to many table. Such a table
usually sits between two indexed tables, for example:
</para>
<programlisting> <programlisting>
CREATE TABLE one_to_many(left INT, right INT) ; CREATE TABLE left (id INT PRIMARY KEY, ...);
CREATE TABLE right (id INT PRIMARY KEY, ...);
CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right);
</programlisting> </programlisting>
<para> <para>
And it is used like this: It is typically used like this:
</para> </para>
<programlisting> <programlisting>
SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right) SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right)
WHERE one_to_many.left = item; WHERE one_to_many.left = <replaceable>item</>;
</programlisting> </programlisting>
<para> <para>
This will return all the items in the right hand table for an entry This will return all the items in the right hand table for an entry
in the left hand table. This is a very common construct in SQL. in the left hand table. This is a very common construct in SQL.
</para> </para>
<para> <para>
Now, this methodology can be cumbersome with a very large number of Now, this methodology can be cumbersome with a very large number of
entries in the one_to_many table. Depending on the order in which entries in the <structname>one_to_many</> table. Often,
data was entered, a join like this could result in an index scan a join like this would result in an index scan
and a fetch for each right hand entry in the table for a particular and a fetch for each right hand entry in the table for a particular
left hand entry. If you have a very dynamic system, there is not much you left hand entry. If you have a very dynamic system, there is not much you
can do. However, if you have some data which is fairly static, you can can do. However, if you have some data which is fairly static, you can
create a summary table with the aggregator. create a summary table with the aggregator.
</para> </para>
<programlisting> <programlisting>
CREATE TABLE summary as SELECT left, int_array_aggregate(right) CREATE TABLE summary as
AS right FROM one_to_many GROUP BY left; SELECT left, int_array_aggregate(right) AS right
FROM one_to_many
GROUP BY left;
</programlisting> </programlisting>
<para> <para>
This will create a table with one row per left item, and an array This will create a table with one row per left item, and an array
of right items. Now this is pretty useless without some way of using of right items. Now this is pretty useless without some way of using
the array, thats why there is an array enumerator. the array; that's why there is an array enumerator. You can do
</para> </para>
<programlisting> <programlisting>
SELECT left, int_array_enum(right) FROM summary WHERE left = item; SELECT left, int_array_enum(right) FROM summary WHERE left = <replaceable>item</>;
</programlisting> </programlisting>
<para> <para>
The above query using int_array_enum, produces the same results as: The above query using <function>int_array_enum</> produces the same results
as
</para> </para>
<programlisting> <programlisting>
SELECT left, right FROM one_to_many WHERE left = item; SELECT left, right FROM one_to_many WHERE left = <replaceable>item</>;
</programlisting> </programlisting>
<para> <para>
The difference is that the query against the summary table has to get The difference is that the query against the summary table has to get
only one row from the table, where as the query against "one_to_many" only one row from the table, whereas the direct query against
must index scan and fetch a row for each entry. <structname>one_to_many</> must index scan and fetch a row for each entry.
</para> </para>
<para> <para>
On our system, an EXPLAIN shows a query with a cost of 8488 gets reduced On one system, an <command>EXPLAIN</> showed a query with a cost of 8488 was
to a cost of 329. The query is a join between the one_to_many table, reduced to a cost of 329. The original query was a join involving the
<structname>one_to_many</> table, which was replaced by:
</para> </para>
<programlisting> <programlisting>
SELECT right, count(right) FROM SELECT right, count(right) FROM
( ( SELECT left, int_array_enum(right) AS right
SELECT left, int_array_enum(right) AS right FROM summary JOIN FROM summary JOIN (SELECT left FROM left_table WHERE left = <replaceable>item</>) AS lefts
(SELECT left FROM left_table WHERE left = item) AS lefts ON (summary.left = lefts.left)
ON (summary.left = lefts.left ) ) AS list
) AS list GROUP BY right ORDER BY count DESC ; GROUP BY right
ORDER BY count DESC;
</programlisting> </programlisting>
</sect1>
</sect2>
</sect1>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<!-- $PostgreSQL: pgsql/doc/src/sgml/oid2name.sgml,v 1.3 2007/12/10 05:32:51 tgl Exp $ -->
<sect1 id="oid2name"> <sect1 id="oid2name">
<title>oid2name</title> <title>oid2name</title>
<indexterm zone="oid2name"> <indexterm zone="oid2name">
<primary>oid2name</primary> <primary>oid2name</primary>
</indexterm> </indexterm>
<para> <para>
This utility allows administrators to examine the file structure used by <application>oid2name</> is a utility program that helps administrators to
PostgreSQL. To make use of it, you need to be familiar with the file examine the file structure used by PostgreSQL. To make use of it, you need
structure, which is described in <xref linkend="storage">. to be familiar with the database file structure, which is described in
<xref linkend="storage">.
</para> </para>
<sect2> <note>
<title>Overview</title>
<para>
<literal>oid2name</literal> connects to the database and extracts OID,
filenode, and table name information. You can also have it show database
OIDs and tablespace OIDs.
</para>
<para> <para>
When displaying specific tables, you can select which tables to show by The name <quote>oid2name</> is historical, and is actually rather
using -o, -f and -t. The first switch takes an OID, the second takes misleading, since most of the time when you use it, you will really
a filenode, and the third takes a tablename (actually, it's a LIKE be concerned with tables' filenode numbers (which are the file names
pattern, so you can use things like "foo%"). Note that you can use as many visible in the database directories). Be sure you understand the
of these switches as you like, and the listing will include all objects difference between table OIDs and table filenodes!
matched by any of the switches. Also note that these switches can only
show objects in the database given in -d.
</para> </para>
</note>
<sect2>
<title>Overview</title>
<para> <para>
If you don't give any of -o, -f or -t it will dump all the tables in the <application>oid2name</application> connects to a target database and
database given in -d. If you don't give -d, it will show a database extracts OID, filenode, and/or table name information. You can also have
listing. Alternatively you can give -s to get a tablespace listing. it show database OIDs or tablespace OIDs. The program is controlled by
a large number of command-line switches, as shown in
<xref linkend="oid2name-switches">.
</para> </para>
<table>
<title>Additional switches</title> <table id="oid2name-switches">
<title><application>oid2name</> switches</title>
<tgroup cols="2"> <tgroup cols="2">
<thead>
<row>
<entry>Switch</entry>
<entry>Description</entry>
</row>
</thead>
<tbody> <tbody>
<row> <row>
<entry><literal>-i</literal></entry> <entry><literal>-o</literal> <replaceable>oid</></entry>
<entry>include indexes and sequences in the database listing.</entry> <entry>show info for table with OID <replaceable>oid</></entry>
</row> </row>
<row> <row>
<entry><literal>-x</literal></entry> <entry><literal>-f</literal> <replaceable>filenode</></entry>
<entry>display more information about each object shown: tablespace name, <entry>show info for table with filenode <replaceable>filenode</></entry>
schema name, OID. </row>
</entry>
<row>
<entry><literal>-t</literal> <replaceable>tablename_pattern</></entry>
<entry>show info for table(s) matching <replaceable>tablename_pattern</></entry>
</row>
<row>
<entry><literal>-s</literal></entry>
<entry>show tablespace OIDs</entry>
</row> </row>
<row> <row>
<entry><literal>-S</literal></entry> <entry><literal>-S</literal></entry>
<entry>also show system objects (those in information_schema, pg_toast <entry>include system objects (those in
and pg_catalog schemas) <literal>information_schema</literal>, <literal>pg_toast</literal>
and <literal>pg_catalog</literal> schemas)
</entry> </entry>
</row> </row>
<row>
<entry><literal>-i</literal></entry>
<entry>include indexes and sequences in the listing</entry>
</row>
<row>
<entry><literal>-x</literal></entry>
<entry>display more information about each object shown: tablespace name,
schema name, and OID
</entry>
</row>
<row> <row>
<entry><literal>-q</literal></entry> <entry><literal>-q</literal></entry>
<entry>don't display headers(useful for scripting)</entry> <entry>omit headers (useful for scripting)</entry>
</row>
<row>
<entry><literal>-d</literal> <replaceable>database</></entry>
<entry>database to connect to</entry>
</row>
<row>
<entry><literal>-H</literal> <replaceable>host</></entry>
<entry>database server's host</entry>
</row>
<row>
<entry><literal>-p</literal> <replaceable>port</></entry>
<entry>database server's port</entry>
</row>
<row>
<entry><literal>-U</literal> <replaceable>username</></entry>
<entry>username to connect as</entry>
</row>
<row>
<entry><literal>-P</literal> <replaceable>password</></entry>
<entry>password (deprecated &mdash; putting this on the command line
is a security hazard)</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
<para>
To display specific tables, select which tables to show by
using <literal>-o</>, <literal>-f</> and/or <literal>-t</>.
<literal>-o</> takes an OID,
<literal>-f</> takes a filenode,
and <literal>-t</> takes a tablename (actually, it's a LIKE
pattern, so you can use things like <literal>foo%</>).
You can use as many
of these switches as you like, and the listing will include all objects
matched by any of the switches. But note that these switches can only
show objects in the database given by <literal>-d</>.
</para>
<para>
If you don't give any of <literal>-o</>, <literal>-f</> or <literal>-t</>,
but do give <literal>-d</>, it will list all tables in the database
named by <literal>-d</>. In this mode, the <literal>-S</> and
<literal>-i</> switches control what gets listed.
</para>
<para>
If you don't give <literal>-d</> either, it will show a listing of database
OIDs. Alternatively you can give <literal>-s</> to get a tablespace
listing.
</para>
</sect2> </sect2>
<sect2> <sect2>
<title>Examples</title> <title>Examples</title>
<programlisting> <programlisting>
$ # what's in this database server, anyway?
$ oid2name $ oid2name
All databases: All databases:
Oid Database Name Tablespace Oid Database Name Tablespace
...@@ -83,7 +170,8 @@ All tablespaces: ...@@ -83,7 +170,8 @@ All tablespaces:
155151 fastdisk 155151 fastdisk
155152 bigdisk 155152 bigdisk
$ cd $PGDATA/17228 $ # OK, let's look into database alvherre
$ cd $PGDATA/base/17228
$ # get top 10 db objects in the default tablespace, ordered by size $ # get top 10 db objects in the default tablespace, ordered by size
$ ls -lS * | head -10 $ ls -lS * | head -10
...@@ -98,6 +186,7 @@ $ ls -lS * | head -10 ...@@ -98,6 +186,7 @@ $ ls -lS * | head -10
-rw------- 1 alvherre alvherre 163840 sep 14 09:50 16699 -rw------- 1 alvherre alvherre 163840 sep 14 09:50 16699
-rw------- 1 alvherre alvherre 122880 sep 6 17:51 16751 -rw------- 1 alvherre alvherre 122880 sep 6 17:51 16751
$ # I wonder what file 155173 is ...
$ oid2name -d alvherre -f 155173 $ oid2name -d alvherre -f 155173
From database "alvherre": From database "alvherre":
Filenode Table Name Filenode Table Name
...@@ -112,7 +201,7 @@ From database "alvherre": ...@@ -112,7 +201,7 @@ From database "alvherre":
155173 accounts 155173 accounts
1155291 accounts_pkey 1155291 accounts_pkey
$ # you can also mix the options, and have more details $ # you can mix the options, and get more details with -x
$ oid2name -d alvherre -t accounts -f 1155291 -x $ oid2name -d alvherre -t accounts -f 1155291 -x
From database "alvherre": From database "alvherre":
Filenode Table Name Oid Schema Tablespace Filenode Table Name Oid Schema Tablespace
...@@ -157,7 +246,7 @@ $ ls -d 155151/* ...@@ -157,7 +246,7 @@ $ ls -d 155151/*
155151/17228/ 155151/PG_VERSION 155151/17228/ 155151/PG_VERSION
$ # Oh, what was database 17228 again? $ # Oh, what was database 17228 again?
$ oid2name $ oid2name
All databases: All databases:
Oid Database Name Tablespace Oid Database Name Tablespace
---------------------------------- ----------------------------------
...@@ -178,28 +267,25 @@ From database "alvherre": ...@@ -178,28 +267,25 @@ From database "alvherre":
Filenode Table Name Filenode Table Name
---------------------- ----------------------
155156 foo 155156 foo
$ # end of sample session.
</programlisting> </programlisting>
</sect2>
<sect2>
<title>Limitations</title>
<para> <para>
You can also get approximate size data for each object using psql. For <application>oid2name</> requires a running database server with
example, non-corrupt system catalogs. It is therefore of only limited use
</para> for recovering from catastrophic database corruption situations.
<programlisting>
SELECT relpages, relfilenode, relname FROM pg_class ORDER BY relpages DESC;
</programlisting>
<para>
Each page is typically 8k. Relpages is updated by VACUUM.
</para> </para>
</sect2> </sect2>
<sect2> <sect2>
<title>Author</title> <title>Author</title>
<para> <para>
b. palmer, <email>bpalmer@crimelabs.net</email> B. Palmer <email>bpalmer@crimelabs.net</email>
</para> </para>
</sect2> </sect2>
</sect1> </sect1>
<!-- $PostgreSQL: pgsql/doc/src/sgml/pageinspect.sgml,v 1.3 2007/12/10 05:32:51 tgl Exp $ -->
<sect1 id="pageinspect"> <sect1 id="pageinspect">
<title>pageinspect</title> <title>pageinspect</title>
<indexterm zone="pageinspect"> <indexterm zone="pageinspect">
<primary>pageinspect</primary> <primary>pageinspect</primary>
</indexterm> </indexterm>
<para> <para>
The functions in this module allow you to inspect the contents of data pages The <filename>pageinspect</> module provides functions that allow you to
at a low level, for debugging purposes. inspect the contents of database pages at a low level, which is useful for
debugging purposes. All of these functions may be used only by superusers.
</para> </para>
<sect2> <sect2>
<title>Functions included</title> <title>Functions</title>
<itemizedlist>
<listitem>
<para>
<literal>get_raw_page</literal> reads one block of the named table and returns a copy as a
bytea field. This allows a single time-consistent copy of the block to be
made. Use of this functions is restricted to superusers.
</para>
</listitem>
<listitem> <variablelist>
<para> <varlistentry>
<literal>page_header</literal> shows fields which are common to all PostgreSQL heap and index <term>
pages. Use of this function is restricted to superusers. <function>get_raw_page(text, int) returns bytea</function>
</para> </term>
<para>
A page image obtained with <literal>get_raw_page</literal> should be passed as argument:
</para>
<programlisting>
regression=# SELECT * FROM page_header(get_raw_page('pg_class',0));
lsn | tli | flags | lower | upper | special | pagesize | version | prune_xid
-----------+-----+-------+-------+-------+---------+----------+---------+-----------
0/24A1B50 | 1 | 1 | 232 | 368 | 8192 | 8192 | 4 | 0
</programlisting>
<para>
The returned columns correspond to the fields in the PageHeaderData struct.
See src/include/storage/bufpage.h for more details.
</para>
</listitem>
<listitem>
<para>
<literal>heap_page_items</literal> shows all line pointers on a heap page. For those line
pointers that are in use, tuple headers are also shown. All tuples are
shown, whether or not the tuples were visible to an MVCC snapshot at the
time the raw page was copied. Use of this function is restricted to
superusers.
</para>
<para>
A heap page image obtained with <literal>get_raw_page</literal> should be passed as argument:
</para>
<programlisting>
test=# SELECT * FROM heap_page_items(get_raw_page('pg_class',0));
</programlisting>
<para>
See src/include/storage/itemid.h and src/include/access/htup.h for
explanations of the fields returned.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<literal>bt_metap()</literal> returns information about the btree index metapage: <function>get_raw_page</function> reads the specified block of the named
</para> table and returns a copy as a <type>bytea</> value. This allows a
<programlisting> single time-consistent copy of the block to be obtained.
test=> SELECT * FROM bt_metap('pg_cast_oid_index'); </para>
-[ RECORD 1 ]----- </listitem>
magic | 340322 </varlistentry>
version | 2
root | 1 <varlistentry>
level | 0 <term>
fastroot | 1 <function>page_header(bytea) returns record</function>
fastlevel | 0 </term>
</programlisting>
</listitem> <listitem>
<para>
<listitem> <function>page_header</function> shows fields that are common to all
<para> <productname>PostgreSQL</> heap and index pages.
<literal>bt_page_stats()</literal> shows information about single btree pages: </para>
</para>
<programlisting> <para>
test=> SELECT * FROM bt_page_stats('pg_cast_oid_index', 1); A page image obtained with <function>get_raw_page</function> should be
-[ RECORD 1 ]-+----- passed as argument. For example:
blkno | 1 </para>
type | l <programlisting>
live_items | 256 test=# SELECT * FROM page_header(get_raw_page('pg_class', 0));
dead_items | 0 lsn | tli | flags | lower | upper | special | pagesize | version | prune_xid
avg_item_size | 12 -----------+-----+-------+-------+-------+---------+----------+---------+-----------
page_size | 8192 0/24A1B50 | 1 | 1 | 232 | 368 | 8192 | 8192 | 4 | 0
free_size | 4056 </programlisting>
btpo_prev | 0
btpo_next | 0 <para>
btpo | 0 The returned columns correspond to the fields in the
btpo_flags | 3 <structname>PageHeaderData</> struct.
</programlisting> See <filename>src/include/storage/bufpage.h</> for details.
</listitem>
<listitem>
<para>
<literal>bt_page_items()</literal> returns information about specific items on btree pages:
</para> </para>
<programlisting> </listitem>
test=> SELECT * FROM bt_page_items('pg_cast_oid_index', 1); </varlistentry>
itemoffset | ctid | itemlen | nulls | vars | data
------------+---------+---------+-------+------+------------- <varlistentry>
1 | (0,1) | 12 | f | f | 23 27 00 00 <term>
2 | (0,2) | 12 | f | f | 24 27 00 00 <function>heap_page_items(bytea) returns setof record</function>
3 | (0,3) | 12 | f | f | 25 27 00 00 </term>
4 | (0,4) | 12 | f | f | 26 27 00 00
5 | (0,5) | 12 | f | f | 27 27 00 00 <listitem>
6 | (0,6) | 12 | f | f | 28 27 00 00 <para>
7 | (0,7) | 12 | f | f | 29 27 00 00 <function>heap_page_items</function> shows all line pointers on a heap
8 | (0,8) | 12 | f | f | 2a 27 00 00 page. For those line pointers that are in use, tuple headers are also
</programlisting> shown. All tuples are shown, whether or not the tuples were visible to
</listitem> an MVCC snapshot at the time the raw page was copied.
</itemizedlist> </para>
<para>
A heap page image obtained with <function>get_raw_page</function> should
be passed as argument. For example:
</para>
<programlisting>
test=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0));
</programlisting>
<para>
See <filename>src/include/storage/itemid.h</> and
<filename>src/include/access/htup.h</> for explanations of the fields
returned.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<function>bt_metap(text) returns record</function>
</term>
<listitem>
<para>
<function>bt_metap</function> returns information about a btree
index's metapage. For example:
</para>
<programlisting>
test=# SELECT * FROM bt_metap('pg_cast_oid_index');
-[ RECORD 1 ]-----
magic | 340322
version | 2
root | 1
level | 0
fastroot | 1
fastlevel | 0
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>
<function>bt_page_stats(text, int) returns record</function>
</term>
<listitem>
<para>
<function>bt_page_stats</function> returns summary information about
single pages of btree indexes. For example:
</para>
<programlisting>
test=# SELECT * FROM bt_page_stats('pg_cast_oid_index', 1);
-[ RECORD 1 ]-+-----
blkno | 1
type | l
live_items | 256
dead_items | 0
avg_item_size | 12
page_size | 8192
free_size | 4056
btpo_prev | 0
btpo_next | 0
btpo | 0
btpo_flags | 3
</programlisting>
</listitem>
</varlistentry>
<varlistentry>
<term>
<function>bt_page_items(text, int) returns setof record</function>
</term>
<listitem>
<para>
<function>bt_page_items</function> returns detailed information about
all of the items on a btree index page. For example:
</para>
<programlisting>
test=# SELECT * FROM bt_page_items('pg_cast_oid_index', 1);
itemoffset | ctid | itemlen | nulls | vars | data
------------+---------+---------+-------+------+-------------
1 | (0,1) | 12 | f | f | 23 27 00 00
2 | (0,2) | 12 | f | f | 24 27 00 00
3 | (0,3) | 12 | f | f | 25 27 00 00
4 | (0,4) | 12 | f | f | 26 27 00 00
5 | (0,5) | 12 | f | f | 27 27 00 00
6 | (0,6) | 12 | f | f | 28 27 00 00
7 | (0,7) | 12 | f | f | 29 27 00 00
8 | (0,8) | 12 | f | f | 2a 27 00 00
</programlisting>
</listitem>
</varlistentry>
</variablelist>
</sect2> </sect2>
</sect1>
</sect1>
This diff is collapsed.
<!-- $PostgreSQL: pgsql/doc/src/sgml/pgbuffercache.sgml,v 2.2 2007/12/10 05:32:51 tgl Exp $ -->
<sect1 id="pgbuffercache"> <sect1 id="pgbuffercache">
<title>pg_buffercache</title> <title>pg_buffercache</title>
<indexterm zone="pgbuffercache"> <indexterm zone="pgbuffercache">
<primary>pg_buffercache</primary> <primary>pg_buffercache</primary>
</indexterm> </indexterm>
<para> <para>
The <literal>pg_buffercache</literal> module provides a means for examining The <filename>pg_buffercache</filename> module provides a means for
what's happening to the buffercache at any given time without having to examining what's happening in the shared buffer cache in real time.
restart or rebuild the server with debugging code added. The intent is to
do for the buffercache what pg_locks does for locks.
</para> </para>
<para> <para>
This module consists of a C function <literal>pg_buffercache_pages()</literal> The module provides a C function <function>pg_buffercache_pages</function>
that returns a set of records, plus a view <literal>pg_buffercache</literal> that returns a set of records, plus a view
to wrapper the function. <structname>pg_buffercache</structname> that wraps the function for
convenient use.
</para> </para>
<para> <para>
By default public access is REVOKED from both of these, just in case there By default public access is revoked from both of these, just in case there
are security issues lurking. are security issues lurking.
</para> </para>
<sect2> <sect2>
<title>Notes</title> <title>The <structname>pg_buffercache</structname> view</title>
<para> <para>
The definition of the columns exposed in the view is: The definitions of the columns exposed by the view are:
</para> </para>
<programlisting>
Column | references | Description <table>
----------------+----------------------+------------------------------------ <title><structname>pg_buffercache</> Columns</title>
bufferid | | Id, 1..shared_buffers.
relfilenode | pg_class.relfilenode | Refilenode of the relation. <tgroup cols="4">
reltablespace | pg_tablespace.oid | Tablespace oid of the relation. <thead>
reldatabase | pg_database.oid | Database for the relation. <row>
relblocknumber | | Offset of the page in the relation. <entry>Name</entry>
isdirty | | Is the page dirty? <entry>Type</entry>
usagecount | | Page LRU count <entry>References</entry>
</programlisting> <entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><structfield>bufferid</structfield></entry>
<entry><type>integer</type></entry>
<entry></entry>
<entry>ID, in the range 1..<varname>shared_buffers</></entry>
</row>
<row>
<entry><structfield>relfilenode</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal>pg_class.relfilenode</literal></entry>
<entry>Relfilenode of the relation</entry>
</row>
<row>
<entry><structfield>reltablespace</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal>pg_tablespace.oid</literal></entry>
<entry>Tablespace OID of the relation</entry>
</row>
<row>
<entry><structfield>reldatabase</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal>pg_database.oid</literal></entry>
<entry>Database OID of the relation</entry>
</row>
<row>
<entry><structfield>relblocknumber</structfield></entry>
<entry><type>bigint</type></entry>
<entry></entry>
<entry>Page number within the relation</entry>
</row>
<row>
<entry><structfield>isdirty</structfield></entry>
<entry><type>boolean</type></entry>
<entry></entry>
<entry>Is the page dirty?</entry>
</row>
<row>
<entry><structfield>usagecount</structfield></entry>
<entry><type>smallint</type></entry>
<entry></entry>
<entry>Page LRU count</entry>
</row>
</tbody>
</tgroup>
</table>
<para> <para>
There is one row for each buffer in the shared cache. Unused buffers are There is one row for each buffer in the shared cache. Unused buffers are
shown with all fields null except bufferid. shown with all fields null except <structfield>bufferid</>. Shared system
catalogs are shown as belonging to database zero.
</para> </para>
<para> <para>
Because the cache is shared by all the databases, there are pages from Because the cache is shared by all the databases, there will normally be
relations not belonging to the current database. pages from relations not belonging to the current database. This means
that there may not be matching join rows in <structname>pg_class</> for
some rows, or that there could even be incorrect joins. If you are
trying to join against <structname>pg_class</>, it's a good idea to
restrict the join to rows having <structfield>reldatabase</> equal to
the current database's OID or zero.
</para> </para>
<para> <para>
When the pg_buffercache view is accessed, internal buffer manager locks are When the <structname>pg_buffercache</> view is accessed, internal buffer
taken, and a copy of the buffer cache data is made for the view to display. manager locks are taken for long enough to copy all the buffer state
This ensures that the view produces a consistent set of results, while not data that the view will display.
blocking normal buffer activity longer than necessary. Nonetheless there This ensures that the view produces a consistent set of results, while not
blocking normal buffer activity longer than necessary. Nonetheless there
could be some impact on database performance if this view is read often. could be some impact on database performance if this view is read often.
</para> </para>
</sect2> </sect2>
<sect2> <sect2>
<title>Sample output</title> <title>Sample output</title>
<programlisting>
regression=# \d pg_buffercache;
View "public.pg_buffercache"
Column | Type | Modifiers
----------------+----------+-----------
bufferid | integer |
relfilenode | oid |
reltablespace | oid |
reldatabase | oid |
relblocknumber | bigint |
isdirty | boolean |
usagecount | smallint |
View definition:
SELECT p.bufferid, p.relfilenode, p.reltablespace, p.reldatabase,
p.relblocknumber, p.isdirty, p.usagecount
FROM pg_buffercache_pages() p(bufferid integer, relfilenode oid,
reltablespace oid, reldatabase oid, relblocknumber bigint,
isdirty boolean, usagecount smallint);
<programlisting>
regression=# SELECT c.relname, count(*) AS buffers regression=# SELECT c.relname, count(*) AS buffers
FROM pg_class c INNER JOIN pg_buffercache b FROM pg_buffercache b INNER JOIN pg_class c
ON b.relfilenode = c.relfilenode INNER JOIN pg_database d ON b.relfilenode = c.relfilenode AND
ON (b.reldatabase = d.oid AND d.datname = current_database()) b.reldatabase IN (0, (SELECT oid FROM pg_database
WHERE datname = current_database()))
GROUP BY c.relname GROUP BY c.relname
ORDER BY 2 DESC LIMIT 10; ORDER BY 2 DESC LIMIT 10;
relname | buffers relname | buffers
...@@ -95,26 +148,23 @@ ...@@ -95,26 +148,23 @@
pg_depend | 22 pg_depend | 22
pg_depend_reference_index | 20 pg_depend_reference_index | 20
(10 rows) (10 rows)
regression=#
</programlisting> </programlisting>
</sect2> </sect2>
<sect2> <sect2>
<title>Authors</title> <title>Authors</title>
<itemizedlist>
<listitem> <para>
<para> Mark Kirkwood <email>markir@paradise.net.nz</email>
Mark Kirkwood <email>markir@paradise.net.nz</email> </para>
</para>
</listitem> <para>
<listitem> Design suggestions: Neil Conway <email>neilc@samurai.com</email>
<para>Design suggestions: Neil Conway <email>neilc@samurai.com</email></para> </para>
</listitem>
<listitem> <para>
<para>Debugging advice: Tom Lane <email>tgl@sss.pgh.pa.us</email></para> Debugging advice: Tom Lane <email>tgl@sss.pgh.pa.us</email>
</listitem> </para>
</itemizedlist>
</sect2> </sect2>
</sect1> </sect1>
This diff is collapsed.
<!-- $PostgreSQL: pgsql/doc/src/sgml/pgrowlocks.sgml,v 1.4 2007/12/10 05:32:51 tgl Exp $ -->
<sect1 id="pgrowlocks"> <sect1 id="pgrowlocks">
<title>pgrowlocks</title> <title>pgrowlocks</title>
<indexterm zone="pgrowlocks"> <indexterm zone="pgrowlocks">
<primary>pgrowlocks</primary> <primary>pgrowlocks</primary>
</indexterm> </indexterm>
<para> <para>
The <literal>pgrowlocks</literal> module provides a function to show row The <filename>pgrowlocks</filename> module provides a function to show row
locking information for a specified table. locking information for a specified table.
</para> </para>
<sect2> <sect2>
<title>Overview</title> <title>Overview</title>
<programlisting>
pgrowlocks(text) RETURNS pgrowlocks_type <synopsis>
</programlisting> pgrowlocks(text) returns setof record
</synopsis>
<para> <para>
The parameter is a name of table. And <literal>pgrowlocks_type</literal> is The parameter is the name of a table. The result is a set of records,
defined as: with one row for each locked row within the table. The output columns
are:
</para> </para>
<programlisting>
CREATE TYPE pgrowlocks_type AS (
locked_row TID, -- row TID
lock_type TEXT, -- lock type
locker XID, -- locking XID
multi bool, -- multi XID?
xids xid[], -- multi XIDs
pids INTEGER[] -- locker's process id
);
</programlisting>
<table> <table>
<title>pgrowlocks_type</title> <title><function>pgrowlocks</> output columns</title>
<tgroup cols="2">
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody> <tbody>
<row> <row>
<entry>locked_row</entry> <entry><structfield>locked_row</structfield></entry>
<entry>tuple ID(TID) of each locked rows</entry> <entry><type>tid</type></entry>
<entry>Tuple ID (TID) of locked row</entry>
</row> </row>
<row> <row>
<entry>lock_type</entry> <entry><structfield>lock_type</structfield></entry>
<entry>"Shared" for shared lock, "Exclusive" for exclusive lock</entry> <entry><type>text</type></entry>
<entry><literal>Shared</> for shared lock, or
<literal>Exclusive</> for exclusive lock</entry>
</row> </row>
<row> <row>
<entry>locker</entry> <entry><structfield>locker</structfield></entry>
<entry>transaction ID of locker (Note 1)</entry> <entry><type>xid</type></entry>
<entry>Transaction ID of locker, or multixact ID if multi-transaction</entry>
</row> </row>
<row> <row>
<entry>multi</entry> <entry><structfield>multi</structfield></entry>
<entry>"t" if locker is a multi transaction, otherwise "f"</entry> <entry><type>boolean</type></entry>
<entry>True if locker is a multi-transaction</entry>
</row> </row>
<row> <row>
<entry>xids</entry> <entry><structfield>xids</structfield></entry>
<entry>XIDs of lockers (Note 2)</entry> <entry><type>xid[]</type></entry>
<entry>Transaction IDs of lockers (more than one if multi-transaction)</entry>
</row> </row>
<row> <row>
<entry>pids</entry> <entry><structfield>pids</structfield></entry>
<entry>process ids of locking backends</entry> <entry><type>integer[]</type></entry>
<entry>Process IDs of locking backends (more than one if multi-transaction)</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
<para>
Note1: If the locker is multi transaction, it represents the multi ID.
</para>
<para>
Note2: If the locker is multi, multiple data are shown.
</para>
<para> <para>
The calling sequence for <literal>pgrowlocks</literal> is as follows: <function>pgrowlocks</function> takes <literal>AccessShareLock</> for the
<literal>pgrowlocks</literal> grabs AccessShareLock for the target table and target table and reads each row one by one to collect the row locking
reads each row one by one to get the row locking information. You should information. This is not very speedy for a large table. Note that:
notice that:
</para> </para>
<orderedlist> <orderedlist>
<listitem> <listitem>
<para> <para>
if the table is exclusive locked by someone else, If the table as a whole is exclusive-locked by someone else,
<literal>pgrowlocks</literal> will be blocked. <function>pgrowlocks</function> will be blocked.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<literal>pgrowlocks</literal> may show incorrect information if there's a <function>pgrowlocks</function> is not guaranteed to produce a
new lock or a lock is freeed while its execution. self-consistent snapshot. It is possible that a new row lock is taken,
or an old lock is freed, during its execution.
</para> </para>
</listitem> </listitem>
</orderedlist> </orderedlist>
<para> <para>
<literal>pgrowlocks</literal> does not show the contents of locked rows. If <function>pgrowlocks</function> does not show the contents of locked
you want to take a look at the row contents at the same time, you could do rows. If you want to take a look at the row contents at the same time, you
something like this: could do something like this:
</para>
<programlisting> <programlisting>
SELECT * FROM accounts AS a, pgrowlocks('accounts') AS p WHERE p.locked_ row = a.ctid; SELECT * FROM accounts AS a, pgrowlocks('accounts') AS p
WHERE p.locked_row = a.ctid;
</programlisting> </programlisting>
Be aware however that (as of <productname>PostgreSQL</> 8.3) such a
query will be very inefficient.
</para>
</sect2> </sect2>
<sect2> <sect2>
<title>Example</title> <title>Sample output</title>
<para>
<literal>pgrowlocks</literal> returns the following columns:
</para>
<para>
Here is a sample execution of pgrowlocks:
</para>
<programlisting> <programlisting>
test=# SELECT * FROM pgrowlocks('t1'); test=# SELECT * FROM pgrowlocks('t1');
locked_row | lock_type | locker | multi | xids | pids locked_row | lock_type | locker | multi | xids | pids
------------+-----------+--------+-------+-----------+--------------- ------------+-----------+--------+-------+-----------+---------------
(0,1) | Shared | 19 | t | {804,805} | {29066,29068} (0,1) | Shared | 19 | t | {804,805} | {29066,29068}
(0,2) | Shared | 19 | t | {804,805} | {29066,29068} (0,2) | Shared | 19 | t | {804,805} | {29066,29068}
...@@ -117,7 +124,14 @@ test=# SELECT * FROM pgrowlocks('t1'); ...@@ -117,7 +124,14 @@ test=# SELECT * FROM pgrowlocks('t1');
(0,4) | Exclusive | 804 | f | {804} | {29066} (0,4) | Exclusive | 804 | f | {804} | {29066}
(4 rows) (4 rows)
</programlisting> </programlisting>
</sect2>
<sect2>
<title>Author</title>
<para>
Tatsuo Ishii
</para>
</sect2> </sect2>
</sect1>
</sect1>
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment