テーブルに新しい列を追加するのに問題があります。
数回実行しようとしましたが、10分以上実行した後、ロック時間のためにクエリをキャンセルすることにしました。
ALTER TABLE mytable ADD mycolumn VARCHAR(50);
有用な情報:
私は 興味深い情報 が(HeapTupleHeaderを介して)PostgreSQLがnull許容列を管理する方法について見つけました。
私の最初の推測は、このテーブルには既に8ビットMAXALIGN
の32のnull許容列があるため、HeapTupleHeaderは4バイトの長さです(検証されていないため、その方法がわかりません)。
そのため、新しいnull可能列を追加するには、すべての行でHeapTupleHeaderを更新して新しい8ビットMAXALIGN
を追加する必要があり、パフォーマンスの問題が発生する可能性があります。
そのため、null許容列の数を31に減らすために、null許容列の1つ(実際には実際にはnull許容ではありません)を変更して、私の推測が正しいかどうかを確認しようとしました。
ALTER TABLE mytable ALTER myothercolumn SET NOT NULL;
残念ながら、この変更にも5分以上の非常に長い時間がかかるため、中止しました。
このパフォーマンスコストの原因は何か考えていますか?
ここにはいくつかの誤解があります:
nullビットマップは、ヒープタプルヘッダーのnot部分ではありません。 ドキュメントごと:
固定サイズのヘッダー(ほとんどのマシンで23バイトを占める)があり、その後にオプションのnullビットマップが続きます...
32のnull許容列は、次の2つの理由で不審ではありません。
Nullビットマップは、行ごとに追加されます。ただし、実際のNULL
が少なくとも1つある場合のみ行の値。 Nullable列には直接的な影響はなく、実際のNULL
値のみが影響します。ヌルビットマップが割り当てられている場合、常に完全に割り当てられます(全部またはまったく)。 nullビットマップの実際のサイズは、列ごとに1ビットで、次のバイトに切り上げられます。 現在のソースコードごと:
#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
Nullビットマップは、ヒープタプルヘッダーの後に割り当てられ、その後にオプションのOIDが続き、その後行データが続きます。OIDまたは行データの開始は、ヘッダーのt_hoff
コメントごとのソースコード :
T_hoffはMAXALIGNの倍数でなければならないことに注意してください。
ヒープタプルヘッダーの後に1バイトの空きがあり、23バイトを占めます。したがって、8列までの行のnullビットマップは、追加コストなしで効果的に使用できます。表の9列目では、 t_hoff
がさらにMAXALIGN
(通常は8)バイト進んで、さらに64列を提供します。したがって、次の境界線は72列になります。
PostgreSQLデータベースクラスター(MAXALIGN
を含む)の制御情報を表示するには、DebianマシンへのPostgres 9.3の一般的なインストールの例:
Sudo /usr/lib/postgresql/9.3/bin/pg_controldata /var/lib/postgresql/9.3/main
引用した関連回答の説明 を更新しました。
さて、あなたのALTER TABLE
ステートメントがテーブル全体の書き換えをトリガーしたとしても(おそらくデータタイプを変更します)、250Kは実際にはそれほど大きくなく、中間の適切なマシンでは数秒で済みます(ただし、行が異常に大きい)。 10分以上は、まったく異なる問題を示します。ステートメントは、おそらくテーブルのロックを取得するために待機しています。
pg_stat_activity
のエントリ数の増加は、より多くの開いているトランザクションを意味します-操作の終了を待機する必要があるテーブルへの同時アクセス(ほとんどの場合)を示します。
可能なテーブル膨張を確認し、穏やかなVACUUM mytable
またはより積極的なVACUUM FULL mytable
を試してください。このフォームも排他ロックを取得するため、同じ同時実行の問題が発生する可能性があります。代わりに pg_repack を試すことができます...
最初に、インデックス、トリガー、外部キー、またはその他の制約、特に列に関連する制約について考えられる問題を調べます。特に破損したインデックスが含まれる可能性がありますか?それらすべてのREINDEX TABLE mytable;
またはDROP
を試し、ALTER TABLE
の後に同じトランザクションの後に再度追加してください。
夜間または負荷が少ないときにコマンドを実行してみてください。
ブルートフォースの方法は、サーバーへのアクセスを停止して、再試行することです。
それをピン留めすることができずに、現在のバージョンまたは特に次の9.4にアップグレードすると、mightヘルプが役立ちます。大きなテーブルとロックの詳細について、いくつかの改善が行われました。しかし、DBに問題がある場合は、まずそれを理解する必要があります。