mirror of https://github.com/postgres/postgres
Fix lots of bad markup, bad English, bad explanations. Second round of commits. pgcrypto and pgstandby still to go...REL8_3_STABLE
parent
a3102ce1ef
commit
8828689ae9
@ -1,82 +1,145 @@ |
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/intagg.sgml,v 1.3 2007/12/10 05:32:51 tgl Exp $ --> |
||||
|
||||
<sect1 id="intagg"> |
||||
<title>intagg</title> |
||||
|
||||
|
||||
<indexterm zone="intagg"> |
||||
<primary>intagg</primary> |
||||
</indexterm> |
||||
|
||||
<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> |
||||
|
||||
<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> |
||||
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> |
||||
|
||||
<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> |
||||
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> |
||||
|
||||
<para> |
||||
And it is used like this: |
||||
It is typically used like this: |
||||
</para> |
||||
|
||||
<programlisting> |
||||
SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right) |
||||
WHERE one_to_many.left = item; |
||||
SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right) |
||||
WHERE one_to_many.left = <replaceable>item</>; |
||||
</programlisting> |
||||
|
||||
<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. |
||||
</para> |
||||
|
||||
<para> |
||||
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 |
||||
data was entered, a join like this could result in an index scan |
||||
entries in the <structname>one_to_many</> table. Often, |
||||
a join like this would result in an index scan |
||||
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 |
||||
create a summary table with the aggregator. |
||||
</para> |
||||
|
||||
<programlisting> |
||||
CREATE TABLE summary as SELECT left, int_array_aggregate(right) |
||||
AS right FROM one_to_many GROUP BY left; |
||||
CREATE TABLE summary as |
||||
SELECT left, int_array_aggregate(right) AS right |
||||
FROM one_to_many |
||||
GROUP BY left; |
||||
</programlisting> |
||||
|
||||
<para> |
||||
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 |
||||
the array, thats why there is an array enumerator. |
||||
the array; that's why there is an array enumerator. You can do |
||||
</para> |
||||
|
||||
<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> |
||||
|
||||
<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> |
||||
|
||||
<programlisting> |
||||
SELECT left, right FROM one_to_many WHERE left = item; |
||||
SELECT left, right FROM one_to_many WHERE left = <replaceable>item</>; |
||||
</programlisting> |
||||
|
||||
|
||||
<para> |
||||
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" |
||||
must index scan and fetch a row for each entry. |
||||
only one row from the table, whereas the direct query against |
||||
<structname>one_to_many</> must index scan and fetch a row for each entry. |
||||
</para> |
||||
|
||||
<para> |
||||
On our system, an EXPLAIN shows a query with a cost of 8488 gets reduced |
||||
to a cost of 329. The query is a join between the one_to_many table, |
||||
On one system, an <command>EXPLAIN</> showed a query with a cost of 8488 was |
||||
reduced to a cost of 329. The original query was a join involving the |
||||
<structname>one_to_many</> table, which was replaced by: |
||||
</para> |
||||
|
||||
<programlisting> |
||||
SELECT right, count(right) FROM |
||||
( |
||||
SELECT left, int_array_enum(right) AS right FROM summary JOIN |
||||
(SELECT left FROM left_table WHERE left = item) AS lefts |
||||
ON (summary.left = lefts.left ) |
||||
) AS list GROUP BY right ORDER BY count DESC ; |
||||
SELECT right, count(right) FROM |
||||
( SELECT left, int_array_enum(right) AS right |
||||
FROM summary JOIN (SELECT left FROM left_table WHERE left = <replaceable>item</>) AS lefts |
||||
ON (summary.left = lefts.left) |
||||
) AS list |
||||
GROUP BY right |
||||
ORDER BY count DESC; |
||||
</programlisting> |
||||
</sect1> |
||||
|
||||
</sect2> |
||||
|
||||
</sect1> |
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,124 +1,170 @@ |
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/pageinspect.sgml,v 1.3 2007/12/10 05:32:51 tgl Exp $ --> |
||||
|
||||
<sect1 id="pageinspect"> |
||||
<title>pageinspect</title> |
||||
|
||||
|
||||
<indexterm zone="pageinspect"> |
||||
<primary>pageinspect</primary> |
||||
</indexterm> |
||||
|
||||
<para> |
||||
The functions in this module allow you to inspect the contents of data pages |
||||
at a low level, for debugging purposes. |
||||
The <filename>pageinspect</> module provides functions that allow you to |
||||
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> |
||||
|
||||
<sect2> |
||||
<title>Functions included</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> |
||||
<title>Functions</title> |
||||
|
||||
<listitem> |
||||
<para> |
||||
<literal>page_header</literal> shows fields which are common to all PostgreSQL heap and index |
||||
pages. Use of this function is restricted to superusers. |
||||
</para> |
||||
<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> |
||||
<variablelist> |
||||
<varlistentry> |
||||
<term> |
||||
<function>get_raw_page(text, int) returns bytea</function> |
||||
</term> |
||||
|
||||
<listitem> |
||||
<para> |
||||
<literal>bt_metap()</literal> returns information about the btree index metapage: |
||||
</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> |
||||
|
||||
<listitem> |
||||
<para> |
||||
<literal>bt_page_stats()</literal> shows information about single btree pages: |
||||
</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> |
||||
|
||||
<listitem> |
||||
<para> |
||||
<literal>bt_page_items()</literal> returns information about specific items on btree pages: |
||||
<listitem> |
||||
<para> |
||||
<function>get_raw_page</function> reads the specified block of the named |
||||
table and returns a copy as a <type>bytea</> value. This allows a |
||||
single time-consistent copy of the block to be obtained. |
||||
</para> |
||||
</listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term> |
||||
<function>page_header(bytea) returns record</function> |
||||
</term> |
||||
|
||||
<listitem> |
||||
<para> |
||||
<function>page_header</function> shows fields that are common to all |
||||
<productname>PostgreSQL</> heap and index pages. |
||||
</para> |
||||
|
||||
<para> |
||||
A page image obtained with <function>get_raw_page</function> should be |
||||
passed as argument. For example: |
||||
</para> |
||||
<programlisting> |
||||
test=# 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 |
||||
<structname>PageHeaderData</> struct. |
||||
See <filename>src/include/storage/bufpage.h</> for details. |
||||
</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> |
||||
</itemizedlist> |
||||
</listitem> |
||||
</varlistentry> |
||||
|
||||
<varlistentry> |
||||
<term> |
||||
<function>heap_page_items(bytea) returns setof record</function> |
||||
</term> |
||||
|
||||
<listitem> |
||||
<para> |
||||
<function>heap_page_items</function> 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. |
||||
</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> |
||||
</sect1> |
||||
|
||||
</sect1> |
||||
|
Loading…
Reference in new issue