ここでは、REINDEXの構文、パラメーター、および例を紹介します。
概要
REINDEX [ (オプション [, ...] ) ] {INDEX | テーブル | スキーマ | データベース | システム} [ CONCURRENTLY] 名
ここで、オプションは次のいずれかになります。
CONCURRENTLY [ブール]
TABLESPACE new_tablespace
VERBOSE [ブール値] 説明
REINDEXは、インデックスのテーブルに格納されているデータを使用してインデックスを再構築し、インデックスの古いコピーを置き換えます。 REINDEXを使用するシナリオはいくつかあります。
インデックスが破損し、有効なデータが含まれなくなりました。 理論的にはこれは決して起こらないはずですが、実際には、ソフトウェアのバグやハードウェアの障害によりインデックスが破損する可能性があります。
REINDEXは回復方法を提供します。インデックスは「肥大化」しました。つまり、多くの空またはほぼ空のページが含まれています。 これは、特定の珍しいアクセスパターンの下でPolarDBのBツリーインデックスで発生する可能性があります。
REINDEXは、デッドページなしで新しいバージョンのインデックスを書き込むことにより、インデックスのスペース消費を減らす方法を提供します。インデックスのストレージパラメーター (fillfactorなど) を変更し、変更が完全に反映されていることを確認する必要があります。
インデックスのビルドが
CONCURRENTLYオプションで失敗した場合、このインデックスは "invalid" のままになります。 このようなインデックスは役に立ちませんが、REINDEXを使用して再構築すると便利です。説明無効なインデックスに対して同時ビルドを実行できるのは、
REINDEX INDEXだけです。
パラメーター
INDEX: 指定したインデックスを再作成します。TABLE: 指定されたテーブルのすべてのインデックスを再作成します。 テーブルにセカンダリ "TOAST" テーブルがある場合は、インデックスも再作成されます。SCHEMA: 指定したスキーマのすべてのインデックスを再作成します。 このスキーマのテーブルにセカンダリ "TOAST" テーブルがある場合は、インデックスも再作成されます。 共有システムカタログのインデックスも処理されます。 この形式のREINDEXは、トランザクションブロック内では実行できません。DATABASE: 現在のデータベース内のすべてのインデックスを再作成します。 共有システムカタログのインデックスも処理されます。 この形式のREINDEXは、トランザクションブロック内では実行できません。SYSTEM: 現在のデータベース内のシステムカタログのすべてのインデックスを再作成します。 共有システムカタログのインデックスが含まれています。 ユーザーテーブルのインデックスは処理されません。 この形式のREINDEXは、トランザクションブロック内では実行できません。name: インデックスを再作成する特定のインデックス、テーブル、またはデータベースの名前。 インデックスとテーブル名はスキーマ修飾できます。 現在、REINDEX DATABASEとREINDEX SYSTEMは現在のデータベースのインデックスを再作成できるだけなので、それらのパラメーターは現在のデータベースの名前と一致する必要があります。CONCURRENTLY: このオプションを使用すると、PolarDBは、テーブルへの同時挿入、更新、または削除を防ぐロックを実行せずにインデックスを再構築します。一時テーブルの場合、他のセッションではアクセスできないため、
REINDEXは常に非同時であり、非同時再インデックスの方が安価です。VERBOSE: 各インデックスが再インデックス化されると、進捗レポートを出力します。
注
ユーザーテーブルのインデックスの破損が疑われる場合は、REINDEX indexまたはREINDEX tableを使用して、そのインデックスまたはテーブルのすべてのインデックスを再構築できます。
システムテーブルのインデックスの破損から回復する必要がある場合、hingsはより困難です。 この場合、システムが疑わしいインデックス自体を使用していないことが重要です。 (実際、この種のシナリオでは、破損したインデックスに依存しているため、起動時にサーバープロセスがすぐにクラッシュすることがあります。) 安全に復旧するには、サーバーを -Pオプションで起動する必要があります。これにより、システムカタログの検索にインデックスを使用できなくなります。
これを行う1つの方法は、サーバーをシャットダウンし、コマンドラインに -Pオプションを含めて単一のuserPostgreSQLserverを起動することです。 次に、再構築する量に応じて、REINDEX DATABASE、REINDEX SYSTEM、REINDEX TABLE、またはREINDEX INDEXを発行できます。 疑わしい場合は、REINDEX SYSTEMを使用して、データベース内のすべてのシステムインデックスの再構築を選択します。 次に、シングルユーザーサーバーセッションを終了し、通常のサーバーを再起動します。
または、通常のサーバーセッションは、コマンドラインオプションに -Pを含めて開始できます。 これを行う方法はクライアントによって異なりますが、alllibpqベースのクライアントでは、クライアントを起動する前にPGOPTIONS環境変数を -Pに設定することができます。 この方法では他のクライアントをロックアウトする必要はありませんが、修復が完了するまで他のユーザーが破損したデータベースに接続しないようにするのが賢明かもしれません。
REINDEXは、インデックスの内容が最初から再構築されるという点で、インデックスのドロップと再作成に似ています。 ただし、ロックの考慮事項はかなり異なります。 REINDEXは、インデックスの親テーブルの書き込みをロックアウトしますが、読み取りはロックアウトしません。 また、処理されている特定のインデックスに対してACCESS EXCLUSIVEロックを実行し、そのインデックスを使用しようとする読み取りをブロックします。 対照的に、DROP INDEXは一時的に親テーブルのACCESS EXCLUSIVEロックを取り、書き込みと読み取りの両方をブロックします。 後続のCREATE INDEXは書き込みをロックアウトしますが、読み取りはロックアウトしません。インデックスがないため、読み取りはそれを使用しようとしません。
単一のインデックスまたはテーブルのインデックスを再作成するには、そのインデックスまたはテーブルの所有者である必要があります。 スキーマまたはデータベースのインデックスを再作成するには、そのスキーマまたはデータベースの所有者である必要があります。 特に、スーパーユーザー以外のユーザーが他のユーザーが所有するテーブルのインデックスを再構築できることに注意してください。 ただし、特別な例外として、REINDEX DATABASE、REINDEX SCHEMA、またはREINDEX SYSTEMが非スーパーユーザーによって発行された場合、ユーザーがカタログを所有していない限り、共有カタログのインデックスはスキップされます (通常はそうではありません) 。 もちろん、スーパーユーザーはいつでも何でも再インデックスできます。
パーティションテーブルインデックスまたはパーティションインデックスの再構築はサポートされていません。 ただし、インデックスはパーティションごとに個別に再構築できます。
インデックスの同時再構築
インデックスの再構築は、データベースの通常の操作を妨げる可能性があります。 NormallyPostgreSQLLlockは、書き込みに対してインデックスが再構築されたテーブルをロックし、テーブルの1回のスキャンでインデックス全体の構築を実行します。 他のトランザクションはテーブルを読み取ることができますが、テーブル内の行を挿入、更新、または削除しようとすると、インデックスの再構築が完了するまでブロックされます。 これは、システムがライブプロダクションデータベースである場合に重大な影響を及ぼす可能性がある。 非常に大きなテーブルは、インデックス付けされるのに多くの時間を要することがあり、より小さなテーブルの場合でさえ、インデックス再構築は、プロダクションシステムにとって許容できないほど長い期間の間、ライターを締め出すことがある。
PolarDBは、書き込みの最小限のロックでインデックスの再構築をサポートします。 このメソッドは、REINDEXのCONCURRENTLYオプションを指定することによって呼び出されます。 このオプションを使用する場合、PolarDBは、再構築が必要なインデックスごとにテーブルを2回スキャンし、インデックスを使用する可能性のある既存のすべてのトランザクションの終了を待つ必要があります。 この方法は、標準のインデックスの再構築よりも多くの作業を必要とし、インデックスを変更する未完了のトランザクションを待つ必要があるため、完了するまでにかなり時間がかかります。 ただし、インデックスの再構築中に通常の操作を続行できるため、本番環境でのインデックスの再構築に役立ちます。 もちろん、インデックス再構築によって課される余分なCPU、メモリ、およびI/O負荷は、他の動作を遅くする可能性がある。
以下のステップは、同時再インデックスにおいて行われる。 各ステップは別々のトランザクションで実行されます。 再構築する複数のインデックスがある場合、各ステップは次のステップに移動する前にすべてのインデックスをループします。
新しい一時インデックス定義がカタログ
pg_indexに追加されます。 この定義は、古いインデックスを置き換えるために使用されます。 セッションレベルでのSHARE UPDATE EXCLUSIVEロックは、処理中のスキーマの変更を防ぐために、再インデックス化されているインデックスとその関連するテーブルに適用されます。インデックスを構築する最初のパスは、新しいインデックスごとに行われます。 インデックスが構築されると、そのフラグ
pg_index.indisreadyが「true」に切り替えられて挿入の準備が整い、構築を実行したトランザクションが終了すると他のセッションに表示されます。 このステップは、インデックスごとに別々のトランザクションで行われます。次に、第1のパスが実行されている間に追加されたタプルを追加するために第2のパスが実行される。 このステップはまた、各インデックスについて別々のトランザクションで行われる。
インデックスを参照するすべての制約は、新しいインデックス定義を参照するように変更され、インデックスの名前が変更されます。 この時点で、
pg_index.indisvalidは、新しいインデックスについては「true」に、古いインデックスについては「false」に切り替えられ、キャッシュ無効化が行われ、古いインデックスを参照したすべてのセッションが無効化される。古いインデックスを参照する可能性のあるクエリの実行が完了するのを待った後、古いインデックスは
pg_index.indisreadyを「false」に切り替えて新しいタプルの挿入を防ぎます。古いインデックスは削除されます。 インデックスとテーブルの
SHARE UPDATE EXCLUSIVEセッションロックがリリースされます。
インデックスの再構築中に、一意のインデックスにおける一意性違反などの問題が発生した場合、REINDEXコマンドは失敗しますが、既存のインデックスに加えて「無効な」新しいインデックスを残します。 このインデックスは不完全である可能性があるため、クエリの目的では無視されますが、それでも更新のオーバーヘッドが消費されます。 Thepsql \dコマンドは、次のようなインデックスをINVALIDとして報告します。
postgres=# \dタブ
テーブル "public.tab"
列 | タイプ | 修飾子
--------+---------+-----------
col | 整数 |
Indexes:
"idx" btree (col)
"idx_ccnew" btree (col) INVALID INVALIDとマークされたインデックスの接尾辞がccnewの場合、同時操作中に作成された一時的なインデックスに対応します。推奨される回復方法は、drop indexを使用して削除し、REINDEX CONCURRENTLYを再度試行します。 代わりに、無効なインデックスの接尾辞が付けられている場合、無効なインデックスは、削除できなかった元のインデックスに対応します。推奨される回復方法は、適切な再構築が成功したため、インデックスを削除するだけです。
通常のインデックスビルドでは、同じテーブル上で他の通常のインデックスビルドを同時に実行できますが、同時に実行できるインデックスのビルドは1つだけです。 どちらの場合も、テーブル上の他のタイプのスキーマ変更はその間許可されません。 別の違いは、通常のREINDEX TABLEまたはREINDEX INDEXコマンドはトランザクションブロック内で実行できますが、REINDEX CONCURRENTLYは実行できません。
REINDEX SYSTEMは、システムカタログを同時に再インデックス化できないため、CONCURRENTLYをサポートしていません。
さらに、除外制約のインデックスを同時に再インデックス化することはできません。 このようなインデックスの名前がこのコマンドで直接指定されると、エラーが発生します。 除外制約インデックスを持つテーブルまたはデータベースが同時に再インデックス化された場合、それらのインデックスはスキップされます。 (このようなインデックスは、CONCURRENTLYオプションなしで再インデックスできます。)
例
単一のインデックスを再構築する:
REINDEX INDEX my_index;テーブルmy_tableのすべてのインデックスを再構築します。
REINDEX TABLE my_table;システムインデックスがすでに有効であることを信頼せずに、特定のデータベース内のすべてのインデックスを再構築します。
$ export PGOPTIONS="-P"
$psql broken_db
...
broken_db=> REINDEXデータベースbroken_db;
broken_db=> \q インデックスの再作成中に、関連するリレーションの読み取りおよび書き込み操作をブロックせずに、テーブルのインデックスを再作成します。
REINDEX TABLE CONCURRENTLY my_broken_table;