Support reorganizing tables with non-default operator class.

This commit is contained in:
Takahiro Itagaki 2009-12-28 08:25:00 +00:00
parent 27e6839132
commit 038c07523a
10 changed files with 1083 additions and 957 deletions

View File

@ -3,27 +3,26 @@
#
# Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
#
.PHONY: all install clean
ifdef USE_PGXS
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)
else
subdir = pg_statsinfo
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
endif
all:
make -C bin
make -C lib
SUBDIRS = bin lib
install:
make -C bin install
make -C lib install
all install installdirs uninstall distprep clean distclean maintainer-clean debug:
@for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir $@ || exit; \
done
clean:
make -C bin clean
make -C lib clean
debug:
make -C bin DEBUG_REORG=enable
make -C lib DEBUG_REORG=enable
uninstall:
make -C bin uninstall
make -C lib uninstall
installcheck:
make -C bin installcheck
# We'd like check operations to run all the subtests before failing.
check installcheck:
@CHECKERR=0; for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir $@ || CHECKERR=$$?; \
done; \
exit $$CHECKERR

View File

@ -1,3 +1,3 @@
SET client_min_messages = warning;
\set ECHO none
RESET client_min_messages;
SET client_min_messages = warning;
\set ECHO none
RESET client_min_messages;

View File

@ -5,21 +5,21 @@ SET client_min_messages = warning;
CREATE TABLE tbl_cluster (
col1 int,
col2 timestamp,
":-)" text,
PRIMARY KEY (":-)", col1)
","")" text,
PRIMARY KEY (","")", col1)
) WITH (fillfactor = 70);
CREATE INDEX cidx_cluster ON tbl_cluster (col2, length(":-)"));
ALTER TABLE tbl_cluster CLUSTER ON cidx_cluster;
CREATE INDEX ","") cluster" ON tbl_cluster (col2, length(","")"), ","")" text_pattern_ops);
ALTER TABLE tbl_cluster CLUSTER ON ","") cluster";
CREATE TABLE tbl_only_pkey (
col1 int PRIMARY KEY,
":-)" text
","")" text
);
CREATE TABLE tbl_only_ckey (
col1 int,
col2 timestamp,
":-)" text
","")" text
) WITH (fillfactor = 70);
CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ":-)");
CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ","")");
ALTER TABLE tbl_only_ckey CLUSTER ON cidx_only_ckey;
CREATE TABLE tbl_gistkey (
id integer PRIMARY KEY,
@ -83,10 +83,10 @@ SELECT * FROM tbl_with_dropped_column;
--------+-----------------------------+-----------
col1 | integer | not null
col2 | timestamp without time zone |
:-) | text | not null
,") | text | not null
Indexes:
"tbl_cluster_pkey" PRIMARY KEY, btree (":-)", col1)
"cidx_cluster" btree (col2, length(":-)")) CLUSTER
"tbl_cluster_pkey" PRIMARY KEY, btree (","")", col1)
",") cluster" btree (col2, length(","")"), ","")" text_pattern_ops) CLUSTER
\d tbl_gistkey
Table "public.tbl_gistkey"
@ -104,16 +104,16 @@ Indexes:
--------+-----------------------------+-----------
col1 | integer |
col2 | timestamp without time zone |
:-) | text |
,") | text |
Indexes:
"cidx_only_ckey" btree (col2, ":-)") CLUSTER
"cidx_only_ckey" btree (col2, ","")") CLUSTER
\d tbl_only_pkey
Table "public.tbl_only_pkey"
Column | Type | Modifiers
--------+---------+-----------
col1 | integer | not null
:-) | text |
,") | text |
Indexes:
"tbl_only_pkey_pkey" PRIMARY KEY, btree (col1)
@ -130,8 +130,8 @@ Indexes:
"idx_c1c2" btree (c1, c2)
"idx_c2c1" btree (c2, c1)
SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ":-)" FROM tbl_cluster;
col1 | to_char | :-)
SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ","")" FROM tbl_cluster;
col1 | to_char | ,")
------+---------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2 | 2008-01-01 00:00:00 | king
5 | 2008-01-01 00:30:00 | 1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462309122970249248360558507372126441214970999358314132226659275055927557999505011527820605714701095599716059702745345968620147285174186408891986095523292304843087143214508397626036279952514079896872533965463318088296406206152583523950547457502877599617298355752203375318570113543746034084988471603868999706990048150305440277903164542478230684929369186215805784631115966687130130156185689872372352885092648612494977154218334204285686060146824720771435854874155657069677653720226485447015858801620758474922657226002085584466521458398893944370926591800311388246468157082630100594858704003186480342194897278290641045072636881313739855256117322040245091227700226941127573627280495738108967504018369868368450725799364729060762996941380475654823728997180326802474420629269124859052181004459842150591120249441341728531478105803603371077309182869314710171111683916581726889419758716582152128229518488471.732050807568877293527446341505872366942805253810380628055806979451933016908800037081146186757248575675626141415406703029969945094998952478811655512094373648528093231902305582067974820101084674923265015312343266903322886650672254668921837971227047131660367861588019049986537379859389467650347506576050756618348129606100947602187190325083145829523959832997789824508288714463832917347224163984587855397667958063818353666110843173780894378316102088305524901670023520711144288695990956365797087168498072899493296484283020786408603988738697537582317317831395992983007838702877053913369563312103707264019249106768231199288375641141422016742752102372994270831059898459475987664288897796147837958390228854852903576033852808064381972344661059689722872865264153822664698420021195484155278441181286534507035191650016689294415480846071277143999762926834629577438361895110127148638746976545982451788550975379013880664961911962222957110555242923723192197738262561631468842032853716682938649611917049738836395495938
@ -141,14 +141,14 @@ SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ":-)" FROM tbl_cluster;
(5 rows)
SELECT * FROM tbl_only_ckey ORDER BY 1;
col1 | col2 | :-)
col1 | col2 | ,")
------+--------------------------+-----
1 | Tue Jan 01 00:00:00 2008 | abc
2 | Fri Feb 01 00:00:00 2008 | def
(2 rows)
SELECT * FROM tbl_only_pkey ORDER BY 1;
col1 | :-)
col1 | ,")
------+-----
1 | abc
2 | def

View File

@ -5,25 +5,25 @@ SET client_min_messages = warning;
CREATE TABLE tbl_cluster (
col1 int,
col2 timestamp,
":-)" text,
PRIMARY KEY (":-)", col1)
","")" text,
PRIMARY KEY (","")", col1)
) WITH (fillfactor = 70);
CREATE INDEX cidx_cluster ON tbl_cluster (col2, length(":-)"));
ALTER TABLE tbl_cluster CLUSTER ON cidx_cluster;
CREATE INDEX ","") cluster" ON tbl_cluster (col2, length(","")"), ","")" text_pattern_ops);
ALTER TABLE tbl_cluster CLUSTER ON ","") cluster";
CREATE TABLE tbl_only_pkey (
col1 int PRIMARY KEY,
":-)" text
","")" text
);
CREATE TABLE tbl_only_ckey (
col1 int,
col2 timestamp,
":-)" text
","")" text
) WITH (fillfactor = 70);
CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ":-)");
CREATE INDEX cidx_only_ckey ON tbl_only_ckey (col2, ","")");
ALTER TABLE tbl_only_ckey CLUSTER ON cidx_only_ckey;
CREATE TABLE tbl_gistkey (
@ -95,7 +95,7 @@ SELECT * FROM tbl_with_dropped_column;
\d tbl_only_pkey
\d tbl_with_dropped_column
SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ":-)" FROM tbl_cluster;
SELECT col1, to_char(col2, 'YYYY-MM-DD HH24:MI:SS'), ","")" FROM tbl_cluster;
SELECT * FROM tbl_only_ckey ORDER BY 1;
SELECT * FROM tbl_only_pkey ORDER BY 1;
SELECT * FROM tbl_gistkey ORDER BY 1;

View File

@ -1,123 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<link rel="icon" type="image/png" href="http://pgfoundry.org/images/elephant-icon.png" />
<link rel="stylesheet" type="text/css" href="style.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>pg_reorg: Project Home Page</title>
</head>
<body>
<center><img style="border: none; margin-left: auto; margin-right: auto; " src="http://pgfoundry.org/images/elephantSmall.png" height="75" width="75" />
<hr />
<h1>pg_reorg ホームページへようこそ</h1>
<hr />
</center>
<p>
pg_reorg は PostgreSQL のテーブルを再編成するシェルコマンドです。
共有ロックや排他ロックを取得しないため、再編成中であっても行の参照や更新を行うことができます。
このモジュールは CLUSTER や VACUUM FULL コマンドのより良い代替になります。
</p>
<p>この pg_reorg プロジェクトは <a href="http://www.postgresql.org">PostgreSQL</a> コミュニティによる <a href="http://pgfoundry.org">pgFoundry</a> の中の<a href="http://pgfoundry.org/projects/reorg">プロジェクト</a>です。</p>
<ul>
<li><a href="http://pgfoundry.org/frs/?group_id=1000411">ダウンロード</a> : ソースコードのほか、Windows 用バイナリもダウンロードできます。</li>
<li><a href="http://pgfoundry.org/tracker/?group_id=1000411">バグレポート</li></li>
<li><a href="http://pgfoundry.org/mail/?group_id=1000411">メーリングリスト</a> への参加</li>
</ul>
<div>
<a href="index.html">Here is an English page.</a>
</div>
<hr />
<h2>ドキュメント</h2>
<p>
<a href="pg_reorg-ja.html">ドキュメントはこちら</a>
</p>
<h2>実行時間</h2>
<p>
pg_reorg とclusterdb の比較に示します。
断片化のないソートされた状態 (not fragmented) では clusterdb のほうが高速ですが、完全に断片化した状態 (fully fragmented) では pg_reorg が大幅に高速です。
一般的に、再編成は断片化が進行した状態で実施されることを考えると、pg_reorg は clusterdb よりも実行時間が短いと言えます。
</p>
<center>
<div style="margin: 2em">
<img src="result.png" />
</div>
<table border="1">
<caption>測定環境</caption>
<tr>
<th>大項目</th>
<th>小項目</th>
<th>環境</th>
</tr>
<tr>
<td rowspan="3">ハードウェア</td>
<td>CPU</td>
<td>2 × Xeon 5160 3.00GHz (Dual core)</td>
</tr>
<tr>
<td>メモリ</td>
<td>2GB</td>
</tr>
<tr>
<td>ストレージ</td>
<td>Ultra320 SCSI, 15000rpm (220GB)</td>
</tr>
<tr>
<td rowspan="4">ソフトウェア</td>
<td>OS</td>
<td>RHEL 5.2 (64bit) 2.6.18-92.el5</td>
</tr>
<tr>
<td>DB</td>
<td>PostgreSQL 8.3.3</td>
</tr>
<tr>
<td>pg_reorg</td>
<td>1.0.0</td>
</tr>
<tr>
<td>clusterdb</td>
<td>clusterdb (PostgreSQL) 8.3.3</td>
</tr>
<tr>
<td rowspan="2">データ</td>
<td>スキーマ</td>
<td><code><pre>CREATE TABLE tbl (
id bigserial PRIMARY KEY,
seqkey timestamp NOT NULL,
rndkey timestamp NOT NULL,
filler char(75) NOT NULL
);
CREATE INDEX idx_seq ON tbl (seqkey);
CREATE INDEX idx_rnd ON tbl (rndkey);</pre></code></td>
</tr>
<tr>
<td>件数</td>
<td>1650万件 (約2GB)</td>
</tr>
</table>
</center>
<hr />
<div align="right">
Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
</div>
<!-- PLEASE LEAVE "Powered By GForge" on your site -->
<br />
<center>
<a href="http://gforge.org/"><img src="http://gforge.org/images/pow-gforge.png"
alt="Powered By GForge Collaborative Development Environment" border="0" /></a>
</center>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<link rel="icon" type="image/png" href="http://pgfoundry.org/images/elephant-icon.png" />
<link rel="stylesheet" type="text/css" href="style.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>pg_reorg: Project Home Page</title>
</head>
<body>
<center><img style="border: none; margin-left: auto; margin-right: auto; " src="http://pgfoundry.org/images/elephantSmall.png" height="75" width="75" />
<hr />
<h1>pg_reorg ホームページへようこそ</h1>
<hr />
</center>
<p>
pg_reorg は PostgreSQL のテーブルを再編成するシェルコマンドです。
共有ロックや排他ロックを取得しないため、再編成中であっても行の参照や更新を行うことができます。
このモジュールは CLUSTER や VACUUM FULL コマンドのより良い代替になります。
</p>
<p>この pg_reorg プロジェクトは <a href="http://www.postgresql.org">PostgreSQL</a> コミュニティによる <a href="http://pgfoundry.org">pgFoundry</a> の中の<a href="http://pgfoundry.org/projects/reorg">プロジェクト</a>です。</p>
<ul>
<li><a href="http://pgfoundry.org/frs/?group_id=1000411">ダウンロード</a> : ソースコードのほか、Windows 用バイナリもダウンロードできます。</li>
<li><a href="http://pgfoundry.org/tracker/?group_id=1000411">バグレポート</li></li>
<li><a href="http://pgfoundry.org/mail/?group_id=1000411">メーリングリスト</a> への参加</li>
</ul>
<div>
<a href="index.html">Here is an English page.</a>
</div>
<hr />
<h2>ドキュメント</h2>
<p>
<a href="pg_reorg-ja.html">ドキュメントはこちら</a>
</p>
<h2>実行時間</h2>
<p>
pg_reorg とclusterdb の比較に示します。
断片化のないソートされた状態 (not fragmented) では clusterdb のほうが高速ですが、完全に断片化した状態 (fully fragmented) では pg_reorg が大幅に高速です。
一般的に、再編成は断片化が進行した状態で実施されることを考えると、pg_reorg は clusterdb よりも実行時間が短いと言えます。
</p>
<center>
<div style="margin: 2em">
<img src="result.png" />
</div>
<table border="1">
<caption>測定環境</caption>
<tr>
<th>大項目</th>
<th>小項目</th>
<th>環境</th>
</tr>
<tr>
<td rowspan="3">ハードウェア</td>
<td>CPU</td>
<td>2 × Xeon 5160 3.00GHz (Dual core)</td>
</tr>
<tr>
<td>メモリ</td>
<td>2GB</td>
</tr>
<tr>
<td>ストレージ</td>
<td>Ultra320 SCSI, 15000rpm (220GB)</td>
</tr>
<tr>
<td rowspan="4">ソフトウェア</td>
<td>OS</td>
<td>RHEL 5.2 (64bit) 2.6.18-92.el5</td>
</tr>
<tr>
<td>DB</td>
<td>PostgreSQL 8.3.3</td>
</tr>
<tr>
<td>pg_reorg</td>
<td>1.0.0</td>
</tr>
<tr>
<td>clusterdb</td>
<td>clusterdb (PostgreSQL) 8.3.3</td>
</tr>
<tr>
<td rowspan="2">データ</td>
<td>スキーマ</td>
<td><code><pre>CREATE TABLE tbl (
id bigserial PRIMARY KEY,
seqkey timestamp NOT NULL,
rndkey timestamp NOT NULL,
filler char(75) NOT NULL
);
CREATE INDEX idx_seq ON tbl (seqkey);
CREATE INDEX idx_rnd ON tbl (rndkey);</pre></code></td>
</tr>
<tr>
<td>件数</td>
<td>1650万件 (約2GB)</td>
</tr>
</table>
</center>
</div>
<hr />
<p class="footer">Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-10244036-4");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

View File

@ -1,123 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<link rel="icon" type="image/png" href="http://pgfoundry.org/images/elephant-icon.png" />
<link rel="stylesheet" type="text/css" href="style.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>pg_reorg: Project Home Page</title>
</head>
<body>
<center><img style="border: none; margin-left: auto; margin-right: auto; " src="http://pgfoundry.org/images/elephantSmall.png" height="75" width="75" />
<hr />
<h1>Welcome to the pg_reorg Project Home Page</h1>
<hr />
</center>
<p>
pg_reorg can re-organize tables on a postgres database without any locks so that you can retrieve or update rows in tables being reorganized.
The module is developed to be a better alternative of CLUSTER and VACUUM FULL.
</p>
<p>
The pg_reorg project is a <a href="http://www.postgresql.org">PostgreSQL</a> Community project that is a part of the <a href="http://pgfoundry.org">pgFoundry</a>.
</p>
<p>
The pgFoundry page for the project is at <a href="http://pgfoundry.org/projects/reorg">http://pgfoundry.org/projects/reorg</a>,
where you can find <a href="http://pgfoundry.org/frs/?group_id=1000411">downloads</a>, documentation, bug reports, mailing lists, and a whole lot more.
</p>
<div>
<a href="index-ja.html">日本語のページはこちら。</a>
</div>
<hr />
<h2>Documentation</h2>
<p>
<a href="pg_reorg.html">Documentations here</a>.
</p>
<h2>Execution time</h2>
<p>
Here is a comparison between pg_reorg and clusterdb.
Clusterdb is faster on not fragmented conditions, but pg_reorg is faster on fully fragmented conditions.
Since reorganization is needed only if tables are fragmented, pg_reorg should be faster than clusterdb.
</p>
<center>
<div style="margin: 2em">
<img src="result.png" />
</div>
<table border="1">
<caption>Configuration</caption>
<tr>
<th>Category</th>
<th>Item</th>
<th>Details</th>
</tr>
<tr>
<td rowspan="3">Hardware</td>
<td>CPU</td>
<td>2 * Xeon 5160 3.00GHz (Dual core)</td>
</tr>
<tr>
<td>Memory</td>
<td>2GB</td>
</tr>
<tr>
<td>Storage</td>
<td>Ultra320 SCSI, 15000rpm (220GB)</td>
</tr>
<tr>
<td rowspan="4">Software</td>
<td>OS</td>
<td>RHEL 5.2 (64bit) 2.6.18-92.el5</td>
</tr>
<tr>
<td>DB</td>
<td>PostgreSQL 8.3.3</td>
</tr>
<tr>
<td>pg_reorg</td>
<td>1.0.0</td>
</tr>
<tr>
<td>clusterdb</td>
<td>clusterdb (PostgreSQL) 8.3.3</td>
</tr>
<tr>
<td rowspan="2">Data</td>
<td>Scheme</td>
<td><code><pre>CREATE TABLE tbl (
id bigserial PRIMARY KEY,
seqkey timestamp NOT NULL,
rndkey timestamp NOT NULL,
filler char(75) NOT NULL
);
CREATE INDEX idx_seq ON tbl (seqkey);
CREATE INDEX idx_rnd ON tbl (rndkey);</pre></code></td>
</tr>
<tr>
<td>Rows</td>
<td>16.5 M rows (2GB)</td>
</tr>
</table>
</center>
<hr />
<div align="right">
Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
</div>
<!-- PLEASE LEAVE "Powered By GForge" on your site -->
<br />
<center>
<a href="http://gforge.org/"><img src="http://gforge.org/images/pow-gforge.png"
alt="Powered By GForge Collaborative Development Environment" border="0" /></a>
</center>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<link rel="icon" type="image/png" href="http://pgfoundry.org/images/elephant-icon.png" />
<link rel="stylesheet" type="text/css" href="style.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>pg_reorg: Project Home Page</title>
</head>
<body>
<center><img style="border: none; margin-left: auto; margin-right: auto; " src="http://pgfoundry.org/images/elephantSmall.png" height="75" width="75" />
<hr />
<h1>Welcome to the pg_reorg Project Home Page</h1>
<hr />
</center>
<p>
pg_reorg can re-organize tables on a postgres database without any locks so that you can retrieve or update rows in tables being reorganized.
The module is developed to be a better alternative of CLUSTER and VACUUM FULL.
</p>
<p>
The pg_reorg project is a <a href="http://www.postgresql.org">PostgreSQL</a> Community project that is a part of the <a href="http://pgfoundry.org">pgFoundry</a>.
</p>
<p>
The pgFoundry page for the project is at <a href="http://pgfoundry.org/projects/reorg">http://pgfoundry.org/projects/reorg</a>,
where you can find <a href="http://pgfoundry.org/frs/?group_id=1000411">downloads</a>, documentation, bug reports, mailing lists, and a whole lot more.
</p>
<div>
<a href="index-ja.html">日本語のページはこちら。</a>
</div>
<hr />
<h2>Documentation</h2>
<p>
<a href="pg_reorg.html">Documentations here</a>.
</p>
<h2>Execution time</h2>
<p>
Here is a comparison between pg_reorg and clusterdb.
Clusterdb is faster on not fragmented conditions, but pg_reorg is faster on fully fragmented conditions.
Since reorganization is needed only if tables are fragmented, pg_reorg should be faster than clusterdb.
</p>
<center>
<div style="margin: 2em">
<img src="result.png" />
</div>
<table border="1">
<caption>Configuration</caption>
<tr>
<th>Category</th>
<th>Item</th>
<th>Details</th>
</tr>
<tr>
<td rowspan="3">Hardware</td>
<td>CPU</td>
<td>2 * Xeon 5160 3.00GHz (Dual core)</td>
</tr>
<tr>
<td>Memory</td>
<td>2GB</td>
</tr>
<tr>
<td>Storage</td>
<td>Ultra320 SCSI, 15000rpm (220GB)</td>
</tr>
<tr>
<td rowspan="4">Software</td>
<td>OS</td>
<td>RHEL 5.2 (64bit) 2.6.18-92.el5</td>
</tr>
<tr>
<td>DB</td>
<td>PostgreSQL 8.3.3</td>
</tr>
<tr>
<td>pg_reorg</td>
<td>1.0.0</td>
</tr>
<tr>
<td>clusterdb</td>
<td>clusterdb (PostgreSQL) 8.3.3</td>
</tr>
<tr>
<td rowspan="2">Data</td>
<td>Scheme</td>
<td><code><pre>CREATE TABLE tbl (
id bigserial PRIMARY KEY,
seqkey timestamp NOT NULL,
rndkey timestamp NOT NULL,
filler char(75) NOT NULL
);
CREATE INDEX idx_seq ON tbl (seqkey);
CREATE INDEX idx_rnd ON tbl (rndkey);</pre></code></td>
</tr>
<tr>
<td>Rows</td>
<td>16.5 M rows (2GB)</td>
</tr>
</table>
</center>
<hr />
<p class="footer">Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-10244036-4");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

View File

@ -1,293 +1,293 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>pg_reorg</title>
<link rel="home" title="pg_reorg " href="index.html">
<link rel="stylesheet" TYPE="text/css"href="style.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1><a name="pg_reorg"></a>pg_reorg</h1>
<div><a name="name"></a>
<h2>名前</h2>
pg_reorg -- PostgreSQLデータベース内のテーブルに対して、参照/更新処理をブロックせずに再編成を行います。
</div>
<div>
<a name="synopsis"></a>
<h2>概要</h2>
<p>
<tt>pg_reorg</tt> [<tt><i>connection-options</i></tt>...] [<tt><i>message-options</i></tt>...] [<tt><i>order-options</i></tt>...] [<tt><i>target-options</i></tt>...]
</p>
<p>指定できるオプションには4つのカテゴリがあります。
詳細は<a href="#options">オプション</a>を参照してください。</p>
<dl>
<dt><tt>connection-options</tt> : 接続パラメータ</dt>
<dd><tt>-h</tt> [<tt>--host</tt>] <tt><i>host</i></tt></dd>
<dd><tt>-p</tt> [<tt>--port</tt>] <tt><i>port</i></tt></dd>
<dd><tt>-U</tt> [<tt>--username</tt>] <tt><i>username</i></tt></dd>
<dd><tt>-W</tt> [<tt>--password</tt>]</dd>
<dt><tt>message-options</tt> : 出力メッセージ</dt>
<dd><tt>-q</tt> [<tt>--quiet</tt>]</dd>
<dd><tt>-v</tt> [<tt>--verbose</tt>]</dd>
<dt><tt>order-options</tt> : 並び替えの基準</dt>
<dd><tt>-o</tt> [<tt>--order-by</tt>] <tt><i>columns [,...]</i></tt></dd>
<dd><tt>-n</tt> [<tt>--no-order</tt>]</dd>
<dt><tt>target-options</tt> : 処理対象</dt>
<dd><tt>-a</tt> [<tt>--all</tt>]</dd>
<dd><tt>-d</tt> [<tt>--dbname</tt>] <tt><i>dbname</i></tt></dd>
<dd><tt>-t</tt> [<tt>--table</tt>] <tt><i>table</i></tt></dd>
<dd><tt>-Z</tt> [<tt>--no-analyze</tt>]</dd>
</dl>
</div>
<div><a name="description"></a>
<h2>説明</h2>
<p>pg_reorg は、PostgreSQLデータベース内のテーブルを再編成(行の並び替え)するユーティリティです。
<a href="http://www.postgresql.jp/document/current/html/app-clusterdb.html"><tt>clusterdb</tt></a> と異なり、参照/更新処理をブロックしません。
再編成の方式として、以下のいずれか1つを選択できます。</p>
<ul>
<li>オンライン CLUSTER (cluster index順に行を並び替える)</li>
<li>ユーザの指定した順に行を並び替える</li>
<li>オンライン VACUUM FULL (行の詰め合わせを行う)</li>
</ul>
<p>このユーティリティを使用するためには、以下のことに注意をしてください。</p>
<ul>
<li>このユーティリティは、スーパーユーザのみが実行することができます。</li>
<li>対象のテーブルはPRIMARY KEYを持っている必要があります。</li>
</ul>
</div>
<div><a name="examples"></a>
<h2></h2>
<p><tt>test</tt>というデータベースをオンライン CLUSTER するには、下記のコマンドを実行します。</p>
<PRE><SAMP>$ </SAMP><KBD>pg_reorg test</KBD></PRE>
<p><tt>test</tt>という名前のデータベースの<tt>foo</tt>という1つのテーブルに対してオンライン VACUUM FULL を行うには、下記のコマンドを実行します。</p>
<PRE><SAMP>$ </SAMP><KBD>pg_reorg --no-order --table foo -d test</KBD></PRE><p>
</p>
</div>
<div><a name="options"></a>
<h2>オプション</h2>
<p>pg_reorg では、下記の4種類のコマンドライン引数を指定できます。</p>
<div>
<dl>
<h3>connection-options</h3>
<p>PostgreSQLに接続するためのパラメータです。</p>
<div>
<dl>
<dt><tt>-h <tt><i>host</i></tt><br />
<tt>--host <tt><i>host</i></tt></dt>
<dd>サーバが稼働しているマシンのホスト名を指定します。ホスト名がスラッシュから始まる場合、Unixドメインソケット用のディレクトリとして使用されます。</dd>
<dt><tt>-p <tt><i>port</i></tt><br />
<tt>--port <tt><i>port</i></tt></dt>
<dd>サーバが接続を監視するTCPポートもしくはUnixドメインソケットファイルの拡張子を指定します。</dd>
<dt><tt>-U <tt><i>username</i></tt><br />
<tt>--username <tt><i>username</i></tt></dt>
<dd>接続するユーザ名を指定します。</dd>
<dt><tt>-W</tt><br /><tt>--password</tt></dt>
<dd>データベースに接続する前に、pg_reorg は強制的にパスワード入力を促します。</dd>
<dd>サーバがパスワード認証を要求する場合 pg_reorg は自動的にパスワード入力を促しますので、これが重要になることはありません。
しかし、pg_reorg は、サーバにパスワードが必要かどうかを判断するための接続試行を無駄に行います。
こうした余計な接続試行を防ぐために<tt>-W</tt>の入力が有意となる場合もあります。</dd>
</dl>
</div>
<h3>message-options</h3>
<p>
pg_reorg を実行した際に任意のメッセージを出力するためのパラメータです。
<tt>--quiet</tt>と他の2つのオプションを同時に指定した場合は、<tt>--quiet</tt>のオプションは無視されます。
</p>
<dl>
<dt><tt>-q</tt><br /><tt>--quiet</tt></dt>
<dd>進行メッセージを表示しません。</dd>
<dt><tt>-v</tt><br /><tt>--verbose</tt></dt>
<dd>処理中に詳細な情報を表示します。</dd>
</dl>
<h3>order-options</h3>
<p>pg_reorg を実行する際の並び替えの基準を指定するパラメータです。
何も指定されていない場合は、cluster index順にオンライン CLUSTER を行います。
この2つを同時に指定することはできません。
</p>
<dl>
<dt><tt>-n</tt><br /><tt>--no-order</tt></dt>
<dd>オンライン VACUUM FULL の処理を行います。</dd>
<dt><tt>-o</tt> <tt><i>columns [,...]</i></tt><br />
<tt>--order-by</tt> <tt><i>columns [,...]</i></tt></dt>
<dd>指定したカラムをキーにオンライン CLUSTER を行います。</dd>
</dl>
<h3>target-options</h3>
<p>
pg_reorg を実行する対象を指定するパラメータです。
<tt>--all</tt><tt>--dbname</tt>または<tt>--table</tt>を同時に指定することはできません。
</p>
<dl>
<dt><tt>-a</tt><br /><tt>--all</tt></dt>
<dd>対象となる全てのデータベースに対してオンライン CLUSTER、または、オンラインVACUUM FULLを行います。</dd>
<dt>
<tt>-d <tt><i>dbname</i></tt><br />
<tt>--dbname <tt><i>dbname</i></tt>
</dt>
<dd>オンライン CLUSTER、または、オンライン VACUUM FULL を行うデータベース名を指定します。
データベース名が指定されておらず、<tt>-a</tt>(または<tt>--all</tt>)も指定されていない場合、
データベース名は<tt>PGDATABASE</tt>環境変数から読み取られます。この変数も設定されていない場合は、接続時に指定したユーザ名が使用されます。
</dd>
<dt>
<tt>-t</tt> <tt><i>table</i></tt><br />
<tt>--table</tt> <tt><i>table</i></tt>
</dt>
<dd>オンライン CLUSTER 、または、オンライン VACUUM FULL を行うテーブルを指定します。
このオプションが指定されていない場合は、対象となったデータベースに存在する全ての対象テーブルに対して処理を行います。
</dd>
<dt><tt>-Z</tt><br /><tt>--no-analyze</tt></dt>
<dd>再編成後に ANALYZE を行いません。
このオプションが指定されていない場合は、再編成後に ANALYZE します。</dd>
</dl>
</div>
<div><a name="environment"></a>
<h2>環境変数</h2> <div>
<dl>
<dt>
<tt>PGDATABASE</tt><br />
<tt>PGHOST</tt><br />
<tt>PGPORT</tt><br />
<tt>PGUSER</tt>
</dt>
<dd>デフォルトの接続パラメータです。</dd>
</dl>
</div>
<p>また、このユーティリティは、他のほとんどの PostgreSQL ユーティリティと同様、
libpq でサポートされる環境変数を使用します。詳細については、<a href="http://www.postgresql.jp/document/current/html/libpq-envars.html">環境変数の項目</a>を参照してください。
</p>
</div>
<div><a name="diagnostics"></a>
<h2>トラブルシューティング</h2>
<p>pg_reorg の実行に失敗した場合にエラーが表示されます。
想像されるエラー原因と対処を示します。</p>
<p>致命的なエラーで終了した場合、手動によるクリーンアップを行う必要があります。
クリーンアップは、エラーが発生したデータベースに対して、$PGHOME/share/contrib/uninstall_pg_reorg.sql を実行し、その後、$PGHOME/share/contrib/pg_reorg.sql を実行します。</p>
<dl>
<dt>pg_reorg : reorg database "template1" ... skipped</dt>
<dd><tt>--all</tt>オプションを指定した際に、pg_reorg がインストールされていないデータベースに対して表示されます</dd>
<dd>pg_reorg スキーマのインストールを行ってください。</dd>
<dt>ERROR: pg_reorg is not installed</dt>
<dd><tt>--dbname</tt>で指定したデータベースにpg_reorg がインストールされていません</dd>
<dd>pg_reorg のインストールを行ってください。</dd>
<dt>ERROR: relation "table" has no primary key</dt>
<dd>指定したテーブルにPRIMARY KEYが存在していません。</dd>
<dd>対象のテーブルにPRIMARY KEYの作成を行ってください。(ALTER TABLE ADD PRIMARY KEY)</dd>
<dt>ERROR: relation "table" has no cluster key</dt>
<dd>指定したテーブルに CLUSTER KEYが存在していません。</dd>
<dd>対象のテーブルに CLUSTER KEYの作成を行ってください。(ALTER TABLE CLUSTER)</dd>
<dt>pg_reorg : query failed: ERROR: column "col" does not exist</dt>
<dd><tt>--order-by</tt> で指定したカラムが対象のテーブルに存在していません</dd>
<dd>対象のテーブルに存在するカラムを指定してください。</dd>
<dt>ERROR: permission denied for schema reorg</dt>
<dd>操作を行おうとした対象に権限がありません</dd>
<dd>スーパーユーザで操作を行ってください。</dd>
<dt>pg_reorg : query failed: ERROR: trigger "z_reorg_trigger" for relation "tbl" already exists</dt>
<dd>操作を行おうとした対象にpg_reorg が処理のために作成するトリガと同名のものが存在しています</dd>
<dd>トリガの改名か削除を行ってください。</dd>
<dt>pg_reorg : trigger conflicted for tbl</dt>
<dd>操作を行おうとした対象にpg_reorg が処理のために作成するトリガより後に実行されるトリガが存在しています</dd>
<dd>トリガの改名か削除を行ってください。</dd>
</dl>
</div>
<div><a name="restrictions"></a>
<h2>制約</h2>
<p>pg_reorg を使用する際には、以下の制約があります。以下の制約に関する操作を行った場合の動作は保証されません。注意してください</p>
<h3>一時テーブルへの操作</h3>
<p>pg_reorg では、一時テーブルは操作の対象外です。</p>
<h3>GiSTインデックスの使用</h3>
<p>インデックス種別がGiSTとなっているインデックスがクラスタインデックスとなっている
テーブルはpg_reorg コマンドを使用して操作を行うことはできません。
これは、GiSTインデックスのソート順序は一意ではないため、<tt>ORDER BY</tt>による
ソートが行えないためです。</p>
<h3>DDLコマンドの発行</h3>
<p>
pg_reorg の実行中には、<tt>VACUUM</tt><tt>ANALYZE</tt> <STRONG>以外</STRONG> のDDL操作は行わないでください。
多くの場合、pg_reorg は失敗しロールバックされます。
しかし、以下の操作ではデータが破損するため、非常に危険です。
</p>
<dl>
<dt><tt>TRUNCATE</tt></dt>
<dd>削除した行が pg_reorg 実行後には復元しています。操作結果が消失します。</dd>
<dt><tt>CREATE INDEX</tt></dt>
<dd>スワップされない索引が残る可能性があります。データの不整合が生じます。</dd>
<dt><tt>ALTER TABLE ... ADD COLUMN</tt></dt>
<dd>追加された値が全てNULLに置換されてしまう可能性があります。データが消失します。</dd>
<dt><tt>ALTER TABLE ... ALTER COLUMN TYPE</tt></dt>
<dd>実行するとスキーマで定義された型と実際の格納状態に齟齬をきたします。データの不整合が生じます。</dd>
<dt><tt>ALTER TABLE ... SET TABLESPACE</tt></dt>
<dd>pg_reorg 実行後にrelfilenodeとの不整合が起こるため、対象のテーブルに対する参照/更新操作時にエラーが発生します。</dd>
</dl>
</div>
<div><a name="install"></a>
<h2>インストール方法</h2>
<p>pg_reorg のインストールは、標準のcontribモジュールと同様です。</p>
<h3>ビルド</h3>
<p>pg_reorg のフォルダを$PGHOME/contrib/に配置し、make, make installを行ってください。</p>
<h3>データベースへの登録</h3>
<p>PostgreSQLを起動し、対象のデータベースに対して $PGHOME/share/contrib にある pg_reorg.sql を実行し、インストールを行ってください。</p>
</div>
<div><a name="requirement"></a>
<h2>動作環境</h2>
<dl>
<dt>PostgreSQLバージョン</dt><dd>PostgreSQL 8.3</dd>
<dt>OS</dt><dd>RHEL 5.2, Windows XP SP3</dd>
<dt>ディスク容量</dt><dd>処理対象のテーブル、インデックスサイズの2倍以上のディスク空き容量</dd>
</dl>
</div>
<div><a name="seealso"></a>
<h2>関連項目</h2>
<a href="http://www.postgresql.jp/document/current/html/app-clusterdb.html"><i><tt>clusterdb</tt></i></a>,
<a href="http://www.postgresql.jp/document/current/html/app-vacuumdb.html"><i><tt>vacuumdb</tt></i></a>
</div>
<hr>
<p align="right"><font size="2">
Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
</font></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>pg_reorg</title>
<link rel="home" title="pg_reorg " href="index.html">
<link rel="stylesheet" TYPE="text/css"href="style.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1 id="pg_reorg">pg_reorg</h1>
<div class="index">
<ol>
<li><a href="#name">名前</a></li>
<li><a href="#synopsis">概要</a></li>
<li><a href="#description">説明</a></li>
<li><a href="#examples">使用例</a></li>
<li><a href="#options">オプション</a></li>
<li><a href="#environment">環境変数</a></li>
<li><a href="#restrictions">使用上の注意と制約</a></li>
<li><a href="#details">詳細</a></li>
<li><a href="#install">インストール方法</a></li>
<li><a href="#requirement">動作環境</a></li>
<li><a href="#seealso">関連項目</a></li>
</ol>
</div>
<h2 id="name">名前</h2>
pg_reorg -- PostgreSQLデータベース内のテーブルに対して、参照/更新処理をブロックせずに再編成を行います。
<h2 id="synopsis">概要</h2>
<p>
pg_reorg [connection-options...] [message-options...] [order-options...] [target-options...]
</p>
<p>指定できるオプションには4つのカテゴリがあります。
詳細は<a href="#options">オプション</a>を参照してください。</p>
<dl>
<dt>connection-options : 接続パラメータ</dt>
<dd>-h [--host] host</dd>
<dd>-p [--port] port</dd>
<dd>-U [--username] username</dd>
<dd>-W [--password]</dd>
<dt>message-options : 出力メッセージ</dt>
<dd>-q [--quiet]</dd>
<dd>-v [--verbose]</dd>
<dt>order-options : 並び替えの基準</dt>
<dd>-o [--order-by] columns [,...]</dd>
<dd>-n [--no-order]</dd>
<dt>target-options : 処理対象</dt>
<dd>-a [--all]</dd>
<dd>-d [--dbname] dbname</dd>
<dd>-t [--table] table</dd>
<dd>-Z [--no-analyze]</dd>
</dl>
<h2 id="description">説明</h2>
<p>pg_reorg は、PostgreSQLデータベース内のテーブルを再編成(行の並び替え)するユーティリティです。
<a href="http://www.postgresql.jp/document/current/html/app-clusterdb.html">clusterdb</a> と異なり、参照/更新処理をブロックしません。
再編成の方式として、以下のいずれか1つを選択できます。</p>
<ul>
<li>オンライン CLUSTER (cluster index順に行を並び替える)</li>
<li>ユーザの指定した順に行を並び替える</li>
<li>オンライン VACUUM FULL (行の詰め合わせを行う)</li>
</ul>
<p>このユーティリティを使用するためには、以下のことに注意をしてください。</p>
<ul>
<li>このユーティリティは、スーパーユーザのみが実行することができます。</li>
<li>対象のテーブルはPRIMARY KEYを持っている必要があります。</li>
</ul>
<h2 id="examples"></h2>
<p>testというデータベースをオンライン CLUSTER するには、下記のコマンドを実行します。</p>
<PRE><SAMP>$ </SAMP><KBD>pg_reorg test</KBD></PRE>
<p>testという名前のデータベースのfooという1つのテーブルに対してオンライン VACUUM FULL を行うには、下記のコマンドを実行します。</p>
<PRE><SAMP>$ </SAMP><KBD>pg_reorg --no-order --table foo -d test</KBD></PRE><p>
</p>
<h2 id="options">オプション</h2>
<p>pg_reorg では、下記の4種類のコマンドライン引数を指定できます。</p>
<dl>
<h3>connection-options</h3>
<p>PostgreSQLに接続するためのパラメータです。</p>
<dl>
<dt>-h host<br />
--host host</dt>
<dd>サーバが稼働しているマシンのホスト名を指定します。ホスト名がスラッシュから始まる場合、Unixドメインソケット用のディレクトリとして使用されます。</dd>
<dt>-p port<br />
--port port</dt>
<dd>サーバが接続を監視するTCPポートもしくはUnixドメインソケットファイルの拡張子を指定します。</dd>
<dt>-U username<br />
--username username</dt>
<dd>接続するユーザ名を指定します。</dd>
<dt>-W<br />--password</dt>
<dd>データベースに接続する前に、pg_reorg は強制的にパスワード入力を促します。</dd>
<dd>サーバがパスワード認証を要求する場合 pg_reorg は自動的にパスワード入力を促しますので、これが重要になることはありません。
しかし、pg_reorg は、サーバにパスワードが必要かどうかを判断するための接続試行を無駄に行います。
こうした余計な接続試行を防ぐために-Wの入力が有意となる場合もあります。</dd>
</dl>
<h3>message-options</h3>
<p>
pg_reorg を実行した際に任意のメッセージを出力するためのパラメータです。
--quietと他の2つのオプションを同時に指定した場合は、--quietのオプションは無視されます。
</p>
<dl>
<dt>-q<br />--quiet</dt>
<dd>進行メッセージを表示しません。</dd>
<dt>-v<br />--verbose</dt>
<dd>処理中に詳細な情報を表示します。</dd>
</dl>
<h3>order-options</h3>
<p>pg_reorg を実行する際の並び替えの基準を指定するパラメータです。
何も指定されていない場合は、cluster index順にオンライン CLUSTER を行います。
この2つを同時に指定することはできません。
</p>
<dl>
<dt>-n<br />--no-order</dt>
<dd>オンライン VACUUM FULL の処理を行います。</dd>
<dt>-o columns [,...]<br />
--order-by columns [,...]</dt>
<dd>指定したカラムをキーにオンライン CLUSTER を行います。</dd>
</dl>
<h3>target-options</h3>
<p>
pg_reorg を実行する対象を指定するパラメータです。
--allと--dbnameまたは--tableを同時に指定することはできません。
</p>
<dl>
<dt>-a<br />--all</dt>
<dd>対象となる全てのデータベースに対してオンライン CLUSTER、または、オンラインVACUUM FULLを行います。</dd>
<dt>
-d dbname<br />
--dbname dbname
</dt>
<dd>オンライン CLUSTER、または、オンライン VACUUM FULL を行うデータベース名を指定します。
データベース名が指定されておらず、-aまたは--allも指定されていない場合、
データベース名はPGDATABASE環境変数から読み取られます。この変数も設定されていない場合は、接続時に指定したユーザ名が使用されます。
</dd>
<dt>
-t table<br />
--table table
</dt>
<dd>オンライン CLUSTER 、または、オンライン VACUUM FULL を行うテーブルを指定します。
このオプションが指定されていない場合は、対象となったデータベースに存在する全ての対象テーブルに対して処理を行います。
</dd>
<dt>-Z<br />--no-analyze</dt>
<dd>再編成後に ANALYZE を行いません。
このオプションが指定されていない場合は、再編成後に ANALYZE します。</dd>
</dl>
<h2 id="environment">環境変数</h2>
<dl>
<dt>
PGDATABASE<br />
PGHOST<br />
PGPORT<br />
PGUSER
</dt>
<dd>デフォルトの接続パラメータです。</dd>
</dl>
<p>
また、このユーティリティは、他のほとんどの PostgreSQL ユーティリティと同様、libpq でサポートされる環境変数を使用します。詳細については、<a href="http://www.postgresql.jp/document/current/html/libpq-envars.html">環境変数の項目</a>を参照してください。
</p>
<h2 id="diagnostics">トラブルシューティング</h2>
<p>pg_reorg の実行に失敗した場合にエラーが表示されます。
想像されるエラー原因と対処を示します。</p>
<p>致命的なエラーで終了した場合、手動によるクリーンアップを行う必要があります。
クリーンアップは、エラーが発生したデータベースに対して、$PGHOME/share/contrib/uninstall_pg_reorg.sql を実行し、その後、$PGHOME/share/contrib/pg_reorg.sql を実行します。</p>
<dl>
<dt>pg_reorg : reorg database "template1" ... skipped</dt>
<dd>--allオプションを指定した際に、pg_reorg がインストールされていないデータベースに対して表示されます。</dd>
<dd>pg_reorg スキーマのインストールを行ってください</dd>
<dt>ERROR: pg_reorg is not installed</dt>
<dd>--dbnameで指定したデータベースにpg_reorg がインストールされていません。</dd>
<dd>pg_reorg のインストールを行ってください</dd>
<dt>ERROR: relation "table" has no primary key</dt>
<dd>指定したテーブルにPRIMARY KEYが存在していません。</dd>
<dd>対象のテーブルにPRIMARY KEYの作成を行ってください。(ALTER TABLE ADD PRIMARY KEY)</dd>
<dt>ERROR: relation "table" has no cluster key</dt>
<dd>指定したテーブルに CLUSTER KEYが存在していません。</dd>
<dd>対象のテーブルに CLUSTER KEYの作成を行ってください。(ALTER TABLE CLUSTER)</dd>
<dt>pg_reorg : query failed: ERROR: column "col" does not exist</dt>
<dd>--order-by で指定したカラムが対象のテーブルに存在していません。</dd>
<dd>対象のテーブルに存在するカラムを指定してください。</dd>
<dt>ERROR: permission denied for schema reorg</dt>
<dd>操作を行おうとした対象に権限がありません。</dd>
<dd>スーパーユーザで操作を行ってください</dd>
<dt>pg_reorg : query failed: ERROR: trigger "z_reorg_trigger" for relation "tbl" already exists</dt>
<dd>操作を行おうとした対象にpg_reorg が処理のために作成するトリガと同名のものが存在しています。</dd>
<dd>トリガの改名か削除を行ってください</dd>
<dt>pg_reorg : trigger conflicted for tbl</dt>
<dd>操作を行おうとした対象にpg_reorg が処理のために作成するトリガより後に実行されるトリガが存在しています。</dd>
<dd>トリガの改名か削除を行ってください</dd>
</dl>
<h2 id="restrictions">使用上の注意と制約</h2>
<p>pg_reorg を使用する際には、以下の制約があります。以下の制約に関する操作を行った場合の動作は保証されません。注意してください。</p>
<h3>一時テーブルへの操作</h3>
<p>pg_reorg では、一時テーブルは操作の対象外です</p>
<h3>GiSTインデックスの使用</h3>
<p>インデックス種別がGiSTとなっているインデックスがクラスタインデックスとなっている
テーブルはpg_reorg コマンドを使用して操作を行うことはできません。
これは、GiSTインデックスのソート順序は一意ではないため、ORDER BYによる
ソートが行えないためです。</p>
<h3>DDLコマンドの発行</h3>
<p>
pg_reorg の実行中には、VACUUM と ANALYZE <STRONG>以外</STRONG> のDDL操作は行わないでください。
多くの場合、pg_reorg は失敗しロールバックされます。
しかし、以下の操作ではデータが破損するため、非常に危険です。
</p>
<dl>
<dt>TRUNCATE</dt>
<dd>削除した行が pg_reorg 実行後には復元しています。操作結果が消失します。</dd>
<dt>CREATE INDEX</dt>
<dd>スワップされない索引が残る可能性があります。データの不整合が生じます。</dd>
<dt>ALTER TABLE ... ADD COLUMN</dt>
<dd>追加された値が全てNULLに置換されてしまう可能性があります。データが消失します。</dd>
<dt>ALTER TABLE ... ALTER COLUMN TYPE</dt>
<dd>実行するとスキーマで定義された型と実際の格納状態に齟齬をきたします。データの不整合が生じます。</dd>
<dt>ALTER TABLE ... SET TABLESPACE</dt>
<dd>pg_reorg 実行後にrelfilenodeとの不整合が起こるため、対象のテーブルに対する参照/更新操作時にエラーが発生します。</dd>
</dl>
<h2 id="details">詳細</h2>
<p>pg_reorg は reorg スキーマに作業用テーブルを作成し、そこでデータの並び替えを行います。
最後にシステムカタログを直接書き換えることで、元のテーブルと名前を交換しています。</p>
<h2 id="install">インストール方法</h2>
<p>pg_reorg のインストールは、標準のcontribモジュールと同様です。</p>
<h3>ビルド</h3>
<p>pg_reorg のフォルダを$PGHOME/contrib/に配置し、make, make installを行ってください。</p>
<h3>データベースへの登録</h3>
<p>PostgreSQLを起動し、対象のデータベースに対して $PGHOME/share/contrib にある pg_reorg.sql を実行し、インストールを行ってください。</p>
<h2 id="requirement">動作環境</h2>
<dl>
<dt>PostgreSQLバージョン</dt><dd>PostgreSQL 8.3</dd>
<dt>OS</dt><dd>RHEL 5.2, Windows XP SP3</dd>
<dt>ディスク容量</dt><dd>処理対象のテーブル、インデックスサイズの2倍以上のディスク空き容量</dd>
</dl>
<h2 id="seealso">関連項目</h2>
<a href="http://www.postgresql.jp/document/current/html/app-clusterdb.html">clusterdb</a>,
<a href="http://www.postgresql.jp/document/current/html/app-vacuumdb.html">vacuumdb</a>
<hr />
<p class="footer">Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-10244036-4");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

View File

@ -1,276 +1,278 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>pg_reorg</title>
<link rel="home" title="pg_reorg " href="index.html">
<link rel="stylesheet" TYPE="text/css"href="style.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1><a name="pg_reorg"></a>pg_reorg</h1>
<div><a name="name"></a>
<h2>Name</h2>
pg_reorg -- Reorganize tables in PostgreSQL databases without any locks.
</div>
<div><a name="synopsis"></a>
<h2>Synopsis</h2>
<p>
<tt>pg_reorg</tt> [<tt><i>connection-options</i></tt>...] [<tt><i>message-options</i></tt>...] [<tt><i>order-options</i></tt>...] [<tt><i>target-options</i></tt>...]
</p>
<p>There 4 option categories.
See also <a href="#options">options</a> for details.</p>
<dl>
<dt><tt>connection-options</tt></dt>
<dd><tt>-h</tt> [<tt>--host</tt>] <tt><i>host</i></tt></dd>
<dd><tt>-p</tt> [<tt>--port</tt>] <tt><i>port</i></tt></dd>
<dd><tt>-U</tt> [<tt>--username</tt>] <tt><i>username</i></tt></dd>
<dd><tt>-W</tt> [<tt>--password</tt>]</dd>
<dt><tt>message-options</tt></dt>
<dd><tt>-q</tt> [<tt>--quiet</tt>]</dd>
<dd><tt>-v</tt> [<tt>--verbose</tt>]</dd>
<dt><tt>order-options</tt></dt>
<dd><tt>-o</tt> [<tt>--order-by</tt>] <tt><i>columns [,...]</i></tt></dd>
<dd><tt>-n</tt> [<tt>--no-order</tt>]</dd>
<dt><tt>target-options</tt></dt>
<dd><tt>-a</tt> [<tt>--all</tt>]</dd>
<dd><tt>-d</tt> [<tt>--dbname</tt>] <tt><i>dbname</i></tt></dd>
<dd><tt>-t</tt> [<tt>--table</tt>] <tt><i>table</i></tt></dd>
<dd><tt>-Z</tt> [<tt>--no-analyze</tt>]</dd>
</dl>
</div>
<div>
<a name="description"></a>
<h2>Description</h2>
<p>pg_reorg is an utility program to reorganize tables in PostgreSQL databases.
Unlike <a href="http://www.postgresql.jp/document/current/html/app-clusterdb.html"><tt>clusterdb</tt></a>, it doesn't block any selections and updates during reorganization.
You can choose one of the following methods to reorganize.</p>
<ul>
<li>Online CLUSTER (ordered by cluster index)</li>
<li>Ordered by specified columns</li>
<li>Online VACUUM FULL (packing rows only)</li>
</ul>
<p>NOTICE:</p>
<ul>
<li>Only superusers can use the utility.</li>
<li>Target table must have PRIMARY KEY.</li>
</ul>
</div>
<div><a name="examples"></a>
<h2>Examples</h2>
<p>Execute the following command to do online CLUSTER to all tables in <tt>test</tt> database.</p>
<PRE><SAMP>$ </SAMP><KBD>pg_reorg test</KBD></PRE>
<p>Execute the following command to do online VACUUM FULL to <tt>foo</tt> table in <tt>test</tt> database.</p>
<PRE><SAMP>$ </SAMP><KBD>pg_reorg --no-order --table foo -d test</KBD></PRE><p>
</p></div>
<div><a name="options"></a>
<h2>Options</h2>
<p>pg_reorg has command line options in 4 categolies.</p>
<div>
<dl>
<h3>connection-options</h3>
<p>Parameters to connect PostgreSQL.</p>
<div>
<dl>
<dt><tt>-h <tt><i>host</i></tt><br />
<tt>--host <tt><i>host</i></tt></dt>
<dd>Specifies the host name of the machine on which the server is running. If the value begins with a slash, it is used as the directory for the Unix domain socket. </dd>
<dt><tt>-p <tt><i>port</i></tt><br />
<tt>--port <tt><i>port</i></tt></dt>
<dd>Specifies the TCP port or local Unix domain socket file extension on which the server is listening for connections.</dd>
<dt><tt>-U <tt><i>username</i></tt><br />
<tt>--username <tt><i>username</i></tt></dt>
<dd>User name to connect as. </dd>
<dt><tt>-W</tt><br /><tt>--password</tt></dt>
<dd>Force pg_reorg to prompt for a password before connecting to a database.</dd>
<dd>This option is never essential, since pg_reorg will automatically prompt for a password if the server demands password authentication. However, vacuumdb will waste a connection attempt finding out that the server wants a password. In some cases it is worth typing <tt>-W</tt> to avoid the extra connection attempt. </dd>
</dl>
</div>
<h3>message-options</h3>
<p>Specifies message output by pg_reorg.
<tt>--quiet</tt> is ignored if some of the other options are specified.</p>
<dl>
<dt><tt>-q</tt><br /><tt>--quiet</tt></dt>
<dd>Do not display progress messages. </dd>
<dt><tt>-v</tt><br /><tt>--verbose</tt></dt>
<dd>Print detailed information during processing.</dd>
</dl>
<h3>order-options</h3>
<p>Options to order rows.
If not specified, pg_reorg do online CLUSTER using cluster indexes.
Only one option can be specified.
</p>
<dl>
<dt><tt>-n</tt><br /><tt>--no-order</tt></dt>
<dd>Do online VACUUM FULL.</dd>
<dt><tt>-o</tt> <tt><i>columns [,...]</i></tt><br />
<tt>--order-by</tt> <tt><i>columns [,...]</i></tt></dt>
<dd>Do online CLUSTER ordered by specified columns.</dd>
</dl>
<h3>target-options</h3>
<p>
Options to specify target tables or databases.
You cannot use <tt>--all</tt> and <tt>--dbname</tt> or <tt>--table</tt> together.
</p>
<dl>
<dt><tt>-a</tt><br /><tt>--all</tt></dt>
<dd>Reorganize all databases.</dd>
<dt>
<tt>-d <tt><i>dbname</i></tt><br />
<tt>--dbname <tt><i>dbname</i></tt>
</dt>
<dd>Specifies the name of the database to be reorganized. If this is not specified and <tt>-a</tt> (or <tt>--all</tt>) is not used, the database name is read from the environment variable <tt>PGDATABASE</tt>. If that is not set, the user name specified for the connection is used. </dd>
<dt>
<tt>-t</tt> <tt><i>table</i></tt><br />
<tt>--table</tt> <tt><i>table</i></tt>
</dt>
<dd>Reorganize <tt><i>table</i></tt> only. If you don't specify this option, all tables in specified databases are reorganized.</dd>
<dt><tt>-Z</tt><br /><tt>--no-analyze</tt></dt>
<dd>Do ANALYZE after reorganization. If you don't specify this option, ANALYZE is performed automatically after reorg.</dd>
</dl>
</div>
<div><a name="environment"></a>
<h2>Environment</h2> <div>
<dl>
<dt>
<tt>PGDATABASE</tt><br />
<tt>PGHOST</tt><br />
<tt>PGPORT</tt><br />
<tt>PGUSER</tt>
</dt>
<dd>Default connection parameters</dd>
</dl>
</div>
<p>This utility, like most other PostgreSQL utilities, also uses the environment variables supported by libpq (see <a href="http://developer.postgresql.org/pgdocs/postgres/libpq-envars.html">Environment Variables</a>).</p>
</div>
<div><a name="diagnostics"></a>
<h2>Diagnostics</h2>
<p>Error messages are reported when pg_reorg fails.
The following list shows the cause of errors.</p>
<p>You need to cleanup by hand after fatal erros.
To cleanup, execute $PGHOME/share/contrib/uninstall_pg_reorg.sql to the database where the error occured and then execute $PGHOME/share/contrib/pg_reorg.sql. (Do uninstall and reinstall.)</p>
<dl>
<dt>pg_reorg : reorg database "template1" ... skipped</dt>
<dd>pg_reorg is not installed in the database when <tt>--all</tt> option is specified.</dd>
<dd>Do register pg_reorg to the database.</dd>
<dt>ERROR: pg_reorg is not installed</dt>
<dd>pg_reorg is not installed in the database specified by <tt>--dbname</tt>.</dd>
<dd>Do register pg_reorg to the database.</dd>
<dt>ERROR: relation "table" has no primary key</dt>
<dd>The target table doesn't have PRIMARY KEY.</dd>
<dd>Define PRIMARY KEY to the table. (ALTER TABLE ADD PRIMARY KEY)</dd>
<dt>ERROR: relation "table" has no cluster key</dt>
<dd>The target table doesn't have CLUSTER KEY.</dd>
<dd>Define CLUSTER KEY to the table. (ALTER TABLE CLUSTER)</dd>
<dt>pg_reorg : query failed: ERROR: column "col" does not exist</dt>
<dd>The target table doesn't have columns specified by <tt>--order-by</tt> option.</dd>
<dd>Specify existing columns.</dd>
<dt>ERROR: permission denied for schema reorg</dt>
<dd>Permission error.</dd>
<dd>pg_reorg must be executed by superusers.</dd>
<dt>pg_reorg : query failed: ERROR: trigger "z_reorg_trigger" for relation "tbl" already exists</dt>
<dd>The target table already has a trigger named "z_reorg_trigger".</dd>
<dd>Delete or rename the trigger.</dd>
<dt>pg_reorg : trigger conflicted for tbl</dt>
<dd>The target table already has a trigger which follows by "z_reorg_trigger" in alphabetical order.</dd>
<dd>Delete or rename the trigger.</dd>
</dl>
</div>
<div><a name="restrictions"></a>
<h2>Restrictions</h2>
<p>pg_reorg has the following restrictions.
Be careful to avoid data corruptions.</p>
<h3>Temp tables</h3>
<p>pg_reorg cannot reorganize temp tables.</p>
<h3>GiST indexes</h3>
<p>pg_reorg cannot reorganize tables using GiST indexes.</p>
<h3>DDL commands</h3>
<p>You cannot do DDL commands <strong>except</strong> <tt>VACUUM</tt> and <tt>ANALYZE</tt> during pg_reorg.
In many case pg_reorg would fail and rollback collectly, but there are some cases ending with data-corruption .</p>
<dl>
<dt><tt>TRUNCATE</tt></dt>
<dd><tt>TRUNCATE</tt> is lost. Deleted rows still exist after pg_reorg.</dd>
<dt><tt>CREATE INDEX</tt></dt>
<dd>It causes index corruptions.</dd>
<dt><tt>ALTER TABLE ... ADD COLUMN</tt></dt>
<dd>It causes lost of data. Newly added columns are initialized with NULLs.</dd>
<dt><tt>ALTER TABLE ... ALTER COLUMN TYPE</tt></dt>
<dd>It causes data corruptions.</dd>
<dt><tt>ALTER TABLE ... SET TABLESPACE</tt></dt>
<dd>It causes data corruptions by wrong relfilenode.</dd>
</dl>
</div>
<div><a name="install"></a>
<h2>Installations</h2>
<p>pg_reorg can be installed like standard contrib modules.</p>
<h3>Build from source</h3>
<p>Place pg_reorg to $PGHOME/contrib/ and input make, make install.</p>
<h3>Register to database</h3>
<p>Start PostgreSQL and execute pg_reorg.sql in $PGHOME/share/contrib.</p>
</div>
<div><a name="requirement"></a>
<h2>Requirements</h2>
<dl>
<dt>PostgreSQL version</dt><dd>PostgreSQL 8.3</dd>
<dt>OS</dt><dd>RHEL 5.2, Windows XP SP3</dd>
<dt>Disks</dt><dd>Requires amount of disks twice larger than target table and indexes.</dd>
</dl>
</div>
<div><a name="seealso"></a>
<h2>See Also</h2>
<a href="http://developer.postgresql.org/pgdocs/postgres/app-clusterdb.html"><i><tt>clusterdb</tt></i></a>,
<a href="http://developer.postgresql.org/pgdocs/postgres/app-vacuumdb.html"><i><tt>vacuumdb</tt></i></a>
</div>
<hr>
<p align="right"><font size="2">
Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION
</font></p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>pg_reorg</title>
<link rel="home" title="pg_reorg " href="index.html">
<link rel="stylesheet" TYPE="text/css"href="style.css">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1 id="pg_reorg">pg_reorg</h1>
<div class="index">
<ol>
<li><a href="#name">Name</a></li>
<li><a href="#synopsis">Synopsis</a></li>
<li><a href="#description">Description</a></li>
<li><a href="#examples">Examples</a></li>
<li><a href="#options">Options</a></li>
<li><a href="#environment">Environment</a></li>
<li><a href="#restrictions">Restrictions</a></li>
<li><a href="#details">Details</a></li>
<li><a href="#install">Installations</a></li>
<li><a href="#requirement">Requirements</a></li>
<li><a href="#seealso">See Also</a></li>
</ol>
</div>
<h2 id="name">Name</h2>
pg_reorg -- Reorganize tables in PostgreSQL databases without any locks.
<h2 id="synopsis">Synopsis</h2>
<p>
pg_reorg [connection-options...] [message-options...] [order-options...] [target-options...]
</p>
<p>There 4 option categories.
See also <a href="#options">options</a> for details.</p>
<dl>
<dt>connection-options</dt>
<dd>-h [--host] host</dd>
<dd>-p [--port] port</dd>
<dd>-U [--username] username</dd>
<dd>-W [--password]</dd>
<dt>message-options</dt>
<dd>-q [--quiet]</dd>
<dd>-v [--verbose]</dd>
<dt>order-options</dt>
<dd>-o [--order-by] columns [,...]</dd>
<dd>-n [--no-order]</dd>
<dt>target-options</dt>
<dd>-a [--all]</dd>
<dd>-d [--dbname] dbname</dd>
<dd>-t [--table] table</dd>
<dd>-Z [--no-analyze]</dd>
</dl>
<h2 id="description">Description</h2>
<p>pg_reorg is an utility program to reorganize tables in PostgreSQL databases.
Unlike <a href="http://www.postgresql.jp/document/current/html/app-clusterdb.html">clusterdb</a>, it doesn't block any selections and updates during reorganization.
You can choose one of the following methods to reorganize.</p>
<ul>
<li>Online CLUSTER (ordered by cluster index)</li>
<li>Ordered by specified columns</li>
<li>Online VACUUM FULL (packing rows only)</li>
</ul>
<p>NOTICE:</p>
<ul>
<li>Only superusers can use the utility.</li>
<li>Target table must have PRIMARY KEY.</li>
</ul>
<h2 id="examples">Examples</h2>
<p>Execute the following command to do online CLUSTER to all tables in test database.</p>
<PRE><SAMP>$ </SAMP><KBD>pg_reorg test</KBD></PRE>
<p>Execute the following command to do online VACUUM FULL to foo table in test database.</p>
<PRE><SAMP>$ </SAMP><KBD>pg_reorg --no-order --table foo -d test</KBD></PRE><p>
</p>
<h2 id="options">Options</h2>
<p>pg_reorg has command line options in 4 categolies.</p>
<div>
<dl>
<h3>connection-options</h3>
<p>Parameters to connect PostgreSQL.</p>
<div>
<dl>
<dt>-h host<br />
--host host</dt>
<dd>Specifies the host name of the machine on which the server is running. If the value begins with a slash, it is used as the directory for the Unix domain socket. </dd>
<dt>-p port<br />
--port port</dt>
<dd>Specifies the TCP port or local Unix domain socket file extension on which the server is listening for connections.</dd>
<dt>-U username<br />
--username username</dt>
<dd>User name to connect as. </dd>
<dt>-W<br />--password</dt>
<dd>Force pg_reorg to prompt for a password before connecting to a database.</dd>
<dd>This option is never essential, since pg_reorg will automatically prompt for a password if the server demands password authentication. However, vacuumdb will waste a connection attempt finding out that the server wants a password. In some cases it is worth typing -W to avoid the extra connection attempt. </dd>
</dl>
<h3>message-options</h3>
<p>Specifies message output by pg_reorg.
--quiet is ignored if some of the other options are specified.</p>
<dl>
<dt>-q<br />--quiet</dt>
<dd>Do not display progress messages. </dd>
<dt>-v<br />--verbose</dt>
<dd>Print detailed information during processing.</dd>
</dl>
<h3>order-options</h3>
<p>Options to order rows.
If not specified, pg_reorg do online CLUSTER using cluster indexes.
Only one option can be specified.
</p>
<dl>
<dt>-n<br />--no-order</dt>
<dd>Do online VACUUM FULL.</dd>
<dt>-o columns [,...]<br />
--order-by columns [,...]</dt>
<dd>Do online CLUSTER ordered by specified columns.</dd>
</dl>
<h3>target-options</h3>
<p>
Options to specify target tables or databases.
You cannot use --all and --dbname or --table together.
</p>
<dl>
<dt>-a<br />--all</dt>
<dd>Reorganize all databases.</dd>
<dt>
-d dbname<br />
--dbname dbname
</dt>
<dd>Specifies the name of the database to be reorganized. If this is not specified and -a (or --all) is not used, the database name is read from the environment variable PGDATABASE. If that is not set, the user name specified for the connection is used. </dd>
<dt>
-t table<br />
--table table
</dt>
<dd>Reorganize table only. If you don't specify this option, all tables in specified databases are reorganized.</dd>
<dt>-Z<br />--no-analyze</dt>
<dd>Do ANALYZE after reorganization. If you don't specify this option, ANALYZE is performed automatically after reorg.</dd>
</dl>
<h2 id="environment">Environment</h2>
<dl>
<dt>
PGDATABASE<br />
PGHOST<br />
PGPORT<br />
PGUSER
</dt>
<dd>Default connection parameters</dd>
</dl>
<p>This utility, like most other PostgreSQL utilities, also uses the environment variables supported by libpq (see <a href="http://developer.postgresql.org/pgdocs/postgres/libpq-envars.html">Environment Variables</a>).</p>
<h2 id="diagnostics">Diagnostics</h2>
<p>Error messages are reported when pg_reorg fails.
The following list shows the cause of errors.</p>
<p>You need to cleanup by hand after fatal erros.
To cleanup, execute $PGHOME/share/contrib/uninstall_pg_reorg.sql to the database where the error occured and then execute $PGHOME/share/contrib/pg_reorg.sql. (Do uninstall and reinstall.)</p>
<dl>
<dt>pg_reorg : reorg database "template1" ... skipped</dt>
<dd>pg_reorg is not installed in the database when --all option is specified.</dd>
<dd>Do register pg_reorg to the database.</dd>
<dt>ERROR: pg_reorg is not installed</dt>
<dd>pg_reorg is not installed in the database specified by --dbname.</dd>
<dd>Do register pg_reorg to the database.</dd>
<dt>ERROR: relation "table" has no primary key</dt>
<dd>The target table doesn't have PRIMARY KEY.</dd>
<dd>Define PRIMARY KEY to the table. (ALTER TABLE ADD PRIMARY KEY)</dd>
<dt>ERROR: relation "table" has no cluster key</dt>
<dd>The target table doesn't have CLUSTER KEY.</dd>
<dd>Define CLUSTER KEY to the table. (ALTER TABLE CLUSTER)</dd>
<dt>pg_reorg : query failed: ERROR: column "col" does not exist</dt>
<dd>The target table doesn't have columns specified by --order-by option.</dd>
<dd>Specify existing columns.</dd>
<dt>ERROR: permission denied for schema reorg</dt>
<dd>Permission error.</dd>
<dd>pg_reorg must be executed by superusers.</dd>
<dt>pg_reorg : query failed: ERROR: trigger "z_reorg_trigger" for relation "tbl" already exists</dt>
<dd>The target table already has a trigger named "z_reorg_trigger".</dd>
<dd>Delete or rename the trigger.</dd>
<dt>pg_reorg : trigger conflicted for tbl</dt>
<dd>The target table already has a trigger which follows by "z_reorg_trigger" in alphabetical order.</dd>
<dd>Delete or rename the trigger.</dd>
</dl>
<h2 id="restrictions">Restrictions</h2>
<p>pg_reorg has the following restrictions.
Be careful to avoid data corruptions.</p>
<h3>Temp tables</h3>
<p>pg_reorg cannot reorganize temp tables.</p>
<h3>GiST indexes</h3>
<p>pg_reorg cannot reorganize tables using GiST indexes.</p>
<h3>DDL commands</h3>
<p>You cannot do DDL commands <strong>except</strong> VACUUM and ANALYZE during pg_reorg.
In many case pg_reorg would fail and rollback collectly, but there are some cases ending with data-corruption .</p>
<dl>
<dt>TRUNCATE</dt>
<dd>TRUNCATE is lost. Deleted rows still exist after pg_reorg.</dd>
<dt>CREATE INDEX</dt>
<dd>It causes index corruptions.</dd>
<dt>ALTER TABLE ... ADD COLUMN</dt>
<dd>It causes lost of data. Newly added columns are initialized with NULLs.</dd>
<dt>ALTER TABLE ... ALTER COLUMN TYPE</dt>
<dd>It causes data corruptions.</dd>
<dt>ALTER TABLE ... SET TABLESPACE</dt>
<dd>It causes data corruptions by wrong relfilenode.</dd>
</dl>
<h2 id="details">Details</h2>
<p>pg_reorg creates a work table in reorg schema and sorts rows in it.
Then, it updates system catalog directly to swap the work table and the original one.</p>
<h2 id="install">Installations</h2>
<p>pg_reorg can be installed like standard contrib modules.</p>
<h3>Build from source</h3>
<p>Place pg_reorg to $PGHOME/contrib/ and input make, make install.</p>
<h3>Register to database</h3>
<p>Start PostgreSQL and execute pg_reorg.sql in $PGHOME/share/contrib.</p>
<h2 id="requirement">Requirements</h2>
<dl>
<dt>PostgreSQL version</dt><dd>PostgreSQL 8.3</dd>
<dt>OS</dt><dd>RHEL 5.2, Windows XP SP3</dd>
<dt>Disks</dt><dd>Requires amount of disks twice larger than target table and indexes.</dd>
</dl>
<h2 id="seealso">See Also</h2>
<a href="http://developer.postgresql.org/pgdocs/postgres/app-clusterdb.html">clusterdb</a>,
<a href="http://developer.postgresql.org/pgdocs/postgres/app-vacuumdb.html">vacuumdb</a>
<hr />
<p class="footer">Copyright (c) 2008-2009, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-10244036-4");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>

View File

@ -1,12 +1,13 @@
BODY {
margin-top: 3;
margin-left: 3;
margin-right: 3;
margin-bottom: 3;
}
TT,OL,UL,P,BODY,TR,TD,TH,FORM {
font-family: arial,helvetica,sans-serif;
body {
font-family:
Lucida Grande, Verdana, Arial, Helvetica,
'メイリオ',
'Meiryo',
'ヒラギノ角ゴ Pro W3',
'Hiragino Kaku Gothic Pro',
'Osaka',
' Pゴシック',
sans-serif;
color: #202020;
}
@ -16,11 +17,11 @@ HR { margin: 5px 0px 5px 0px }
h2, h3, h4, h5, h6 {
color: Black;
background: none;
padding-top: 0.5em;
padding-bottom: 0.17em;
border-bottom: 1px solid #aaaaaa;
color: Black;
background: none;
padding-top: 0.5em;
padding-bottom: 0.17em;
border-bottom: 1px solid #aaaaaa;
}
H1 { font-size: x-large; font-family: Lucida Grande,verdana,arial,helvetica,sans-serif; }
H2 { font-size: large; font-family: Lucida Grande,verdana,arial,helvetica,sans-serif; }
@ -29,13 +30,7 @@ H4 { padding-left: 2em; font-size: small; font-family: Lucida Grande,verdana,ari
H5 { padding-left: 3em; font-size: x-small; font-family: Lucida Grande,verdana,arial,helvetica,sans-serif; }
H6 { padding-left: 4em; font-size: xx-small; font-family: Lucida Grande,verdana,arial,helvetica,sans-serif; }
dt {
font-size: 110%;
padding-top: 0.5em;
padding-bottom: 0.5em;
}
PRE {
pre {
font-family: courier,sans-serif;
background-color: #FBFBFD;
border: 1px dashed #7E7ECB;
@ -44,63 +39,43 @@ PRE {
overflow: auto;
}
A:link { text-decoration:none; color:#0000EE }
A:visited { text-decoration:none color:#551A8B}
A:active { text-decoration:none; color:#00ff00 }
A:hover { text-decoration:underline; color:#008000 }
.titlebar { color: #000000; text-decoration: none; font-weight: bold; }
A.tablink {
color: #000000;
text-decoration: none;
font-weight: bold;
font-size: small;
}
A.tablink:visited {
color: #000000;
text-decoration: none;
font-weight: bold;
font-size: small;
}
A.tablink:hover {
text-decoration: none;
color: #000000;
font-weight: bold;
font-size: small;
}
A.tabsellink {
color: #ffffcc;
text-decoration: none;
font-weight: bold;
font-size: small;
}
A.tabsellink:visited {
color: #ffffcc;
text-decoration: none;
font-weight: bold;
font-size: small;
}
A.tabsellink:hover {
text-decoration: none;
color: #ffffcc;
font-weight: bold;
font-size: small;
li {
line-height: 1.4em;
}
A.showsource {
color: #000000;
text-decoration: none;
font-size: small;
}
A.showsource:visited {
color: #000000;
text-decoration: none;
font-size: small;
}
A.showsource:hover {
color: #000000;
text-decoration: none;
table {
background: #f9f9f9;
border: 1px solid #aaa;
border-collapse: collapse;
}
th, td {
border: 1px solid #aaa;
padding: 0.2em;
}
thead th {
background: #f2f2f2;
text-align: center;
}
tbody th {
background: #f2f2f2;
text-align: left;
}
div.index {
float:right;
border:thin solid black;
background-color: white;
padding-top: 0.2em;
padding-bottom: 0.2em;
padding-left: 1em;
padding-right: 1em;
margin-left: 0.5em;
}
p.footer {
text-align: right;
font-size: small;
}

View File

@ -8,12 +8,14 @@
#include <unistd.h>
#include "access/genam.h"
#include "access/transam.h"
#include "access/xact.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_type.h"
#include "commands/tablecmds.h"
#include "commands/trigger.h"
@ -55,6 +57,9 @@ static void swap_heap_or_index_files(Oid r1, Oid r2);
#define copy_tuple(tuple, desc) \
PointerGetDatum(SPI_returntuple((tuple), (desc)))
#define IsToken(c) \
(IS_HIGHBIT_SET((c)) || isalnum((unsigned char) (c)) || (c) == '_')
/* check access authority */
static void
must_be_superuser(const char *func)
@ -313,11 +318,32 @@ skip_const(Oid index, char *sql, const char *arg1, const char *arg2)
static char *
skip_ident(Oid index, char *sql)
{
sql = strchr(sql, ' ');
if (sql)
while (*sql && isspace((unsigned char) *sql))
sql++;
if (*sql == '"')
{
sql++;
for (;;)
{
char *end = strchr(sql, '"');
if (end == NULL)
return parse_error(index);
else if (end[1] != '"')
{
end[1] = '\0';
return end + 2;
}
else /* escaped quote ("") */
sql = end + 2;
}
}
else
{
while (*sql && IsToken(*sql))
sql++;
*sql = '\0';
return sql + 2;
return sql + 1;
}
/* error */
@ -325,12 +351,13 @@ skip_ident(Oid index, char *sql)
}
static char *
skip_columns(Oid index, char *sql)
skip_until(Oid index, char *sql, char end)
{
char instr = 0;
int nopen = 1;
int nopen = 0;
for (; *sql && nopen > 0; sql++)
sql++;
for (; *sql && (nopen > 0 || instr != 0 || *sql != end); sql++)
{
if (instr)
{
@ -342,9 +369,7 @@ skip_columns(Oid index, char *sql)
instr = 0;
}
else if (sql[0] == '\\')
{
sql++; // next char is always string
}
sql++; /* next char is always string */
}
else
{
@ -364,10 +389,10 @@ skip_columns(Oid index, char *sql)
}
}
if (nopen == 0)
if (nopen == 0 && instr == 0)
{
sql[-1] = '\0';
return sql;
*sql = '\0';
return sql + 1;
}
/* error */
@ -395,11 +420,14 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table)
/* USING */
sql = skip_const(index, sql, "USING", NULL);
/* type */
stmt->type= sql;
stmt->type = sql;
sql = skip_ident(index, sql);
/* (columns) */
if ((sql = strchr(sql, '(')) == NULL)
parse_error(index);
sql++;
stmt->columns = sql;
sql = skip_columns(index, sql);
sql = skip_until(index, sql, ')');
/* options */
stmt->options = sql;
}
@ -413,6 +441,9 @@ parse_indexdef(IndexDef *stmt, Oid index, Oid table)
* @param index Oid of target index.
* @param table Oid of table of the index.
* @retval Create index DDL for temp table.
*
* FIXME: this function is named get_index_keys, but actually returns
* an expression for ORDER BY clause. get_order_by() might be a better name.
*/
Datum
reorg_get_index_keys(PG_FUNCTION_ARGS)
@ -420,10 +451,107 @@ reorg_get_index_keys(PG_FUNCTION_ARGS)
Oid index = PG_GETARG_OID(0);
Oid table = PG_GETARG_OID(1);
IndexDef stmt;
char *token;
char *next;
StringInfoData str;
Relation indexRel = NULL;
int nattr;
parse_indexdef(&stmt, index, table);
PG_RETURN_TEXT_P(cstring_to_text(stmt.columns));
/*
* FIXME: this is very unreliable implementation but I don't want to
* re-implement customized versions of pg_get_indexdef_string...
*
* TODO: Support ASC/DESC and NULL FIRST/LAST.
*/
initStringInfo(&str);
for (nattr = 0, next = stmt.columns; *next; nattr++)
{
char *opcname;
token = next;
next = skip_until(index, next, ',');
opcname = token + strlen(token);
if (opcname[-1] == '"')
{
opcname--;
for (;;)
{
char *beg = strrchr(opcname, '"');
if (beg == NULL)
parse_error(index);
else if (beg[-1] != '"')
break;
else /* escaped quote ("") */
opcname = beg - 1;
}
}
else
{
while (opcname > token && IsToken(opcname[-1]))
opcname--;
}
if (opcname > token && *opcname)
{
/* lookup default operator name from operator class */
Oid opclass;
Oid oprid;
int16 strategy = BTLessStrategyNumber;
#if PG_VERSION_NUM >= 80300
Oid opcintype;
Oid opfamily;
HeapTuple tp;
Form_pg_opclass opclassTup;
#endif
opclass = OpclassnameGetOpcid(BTREE_AM_OID, opcname);
#if PG_VERSION_NUM >= 80300
/* Retrieve operator information. */
tp = SearchSysCache(CLAOID, ObjectIdGetDatum(opclass), 0, 0, 0);
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for opclass %u", opclass);
opclassTup = (Form_pg_opclass) GETSTRUCT(tp);
opfamily = opclassTup->opcfamily;
opcintype = opclassTup->opcintype;
ReleaseSysCache(tp);
if (!OidIsValid(opcintype))
{
if (indexRel == NULL)
indexRel = index_open(index, NoLock);
opcintype = RelationGetDescr(indexRel)->attrs[nattr]->atttypid;
}
oprid = get_opfamily_member(opfamily, opcintype, opcintype, strategy);
if (!OidIsValid(oprid))
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
strategy, opcintype, opcintype, opfamily);
#else
oprid = get_opclass_member(opclass, 0, strategy);
if (!OidIsValid(oprid))
elog(ERROR, "missing operator %d for %s", strategy, opcname);
#endif
opcname[-1] = '\0';
appendStringInfo(&str, "%s USING %s", token, get_opname(oprid));
}
else
appendStringInfoString(&str, token);
if (*next)
appendStringInfoChar(&str, ',');
}
if (indexRel != NULL)
index_close(indexRel, NoLock);
PG_RETURN_TEXT_P(cstring_to_text(str.data));
}
/**
@ -481,7 +609,19 @@ remove_dropped_columns_and_adjust_attnum(Oid oid, int16 natts1, int16 natts2)
natts2 - natts1, SPI_processed);
/* renumber attnum */
#if PG_VERSION_NUM >= 80300
#if PG_VERSION_NUM >= 80500
execute_with_format(SPI_OK_UPDATE,
"UPDATE pg_catalog.pg_attribute m"
" SET attnum = (SELECT count(*) FROM pg_attribute a"
" WHERE m.attrelid = a.attrelid"
" AND m.attnum >= a.attnum"
" AND a.attnum > 0 AND NOT a.attisdropped)"
" WHERE attrelid = %u AND attnum > 0 AND NOT attisdropped",
oid);
if (SPI_processed != natts2)
elog(ERROR, "cannot update %d columns (%u columns updated)",
natts2, SPI_processed);
#elif PG_VERSION_NUM >= 80300
execute_with_format(SPI_OK_UPDATE,
"UPDATE pg_catalog.pg_attribute"
" SET attnum = (SELECT count(*) FROM pg_attribute a"
@ -676,12 +816,21 @@ reorg_swap(PG_FUNCTION_ARGS)
/* adjust key attnum if the target table has dropped columns */
if (natts1 != natts2)
{
#if PG_VERSION_NUM >= 80500
execute_with_format(SPI_OK_UPDATE,
"UPDATE pg_catalog.pg_index m SET indkey = n.indkey"
" FROM pg_catalog.pg_index n"
" WHERE m.indexrelid = %u"
" AND n.indexrelid = 'reorg.index_%u'::regclass",
idx1, idx1);
#else
execute_with_format(SPI_OK_UPDATE,
"UPDATE pg_catalog.pg_index SET indkey = n.indkey"
" FROM pg_catalog.pg_index n"
" WHERE pg_catalog.pg_index.indexrelid = %u"
" AND n.indexrelid = 'reorg.index_%u'::regclass",
idx1, idx1);
#endif
if (SPI_processed != 1)
elog(ERROR, "failed to update pg_index.indkey (%u rows updated)", SPI_processed);
}