GreenplumはMPPアーキテクチャを採用した並列処理型データベースであり、大量のメモリを積極的に活用して高速処理を実現する。しかし、メモリ使用量が制御を超えると、セグメントプロセスがOSによって強制終了(OOM Killer)され、クラスタ全体の安定性に深刻な影響を及ぼす可能性がある。
メモリオーバーフローを引き起こす主な要因
- ノードあたりの物理メモリ不足
- OSカーネルパラメータ(例:vm.overcommit_memory)の不適切な設定
- データ分布の偏り(スキュー)により特定セグメントに過大な負荷が集中
- 集約やウィンドウ関数で分布キー以外のカラムを使用し、再分散時にメモリ需要が急増
- 統計情報の古さやインデックスの劣化による非効率な実行計画
メモリオーバーフローの回避策
- SQLクエリの最適化(結合順序、フィルタ条件の改善など)
- リソースキューによる同時実行クエリ数の制限
- ホストあたりのセグメント数を減らし、各セグメントの利用可能メモリを増加
- gp_vmem_protect_limit によるセグメント単位の仮想メモリ上限設定
- statement_mem をセッション単位で調整し、個別クエリのメモリ使用量を制御
OSカーネルパラメータの推奨設定
Huge PageはGreenplumのPostgreSQLバージョンでは未対応のため無効化すること。また、メモリオーバーコミットポリシーは以下のように設定:
# SWAP使用時は2、未使用時は0を推奨
vm.overcommit_memory = 2
vm.overcommit_ratio = 98 # 計算式に基づき調整
データベースパラメータの要点
- gp_vmem_protect_limit:1セグメントが使用可能な最大VMEM(MB単位)
- runaway_detector_activation_percent(デフォルト90):この閾値を超えると高メモリ消費クエリが自動キャンセルされる
- statement_mem(デフォルト125MB):1クエリが使用可能なメモリ量。超過時はディスクにspill
- gp_workfile_limit_files_per_query:spillファイル数の上限(デフォルト100,000)。超過時はクエリが中止
メモリパラメータ計算例
256GB RAM + 64GB SWAP のホストで、プライマリ8セグメント+ミラー8セグメントを配置。フェイルオーバー時最大11セグメント稼働を想定:
# 利用可能メモリ総量(経験則に基づく)
gp_vmem = ((256 + 64) - (7.5 + 0.05 * 256)) / 1.7 ≈ 176 GB
# オーバーコミット比
vm.overcommit_ratio = (256 - (0.026 * 176)) / 256 ≈ 98%
# セグメントあたり上限
gp_vmem_protect_limit = (176 * 1024) / 11 ≈ 16384 MB
リソースキューによる制御
リソースキューはLinuxのcgroupと類似した仕組みで、同時実行数やメモリ総量を制限できる:
CREATE RESOURCE QUEUE heavy_queries
WITH (
ACTIVE_STATEMENTS = 5,
MEMORY_LIMIT = '20GB',
PRIORITY = HIGH
);
注意点として、gp_resqueue_memory_policy = 'auto' の場合、statement_mem がリソースキューの MEMORY_LIMIT より優先される可能性がある。
典型的なエラーケースと対応
ケース1: VMEM使用量が90%超過によるクエリキャンセル
ERROR: Canceling query because of high VMEM usage. Used: 7296MB, available 816MB...
対応策:
- gp_vmem_protect_limit を適正値に再設定(公式計算機利用)
- 関連テーブルおよびシステムカタログ(pg_classなど)に対して VACUUM/ANALYZE/REINDEX 実施
ケース2: statement_mem不足
ERROR: insufficient memory reserved for statement
対応策:セッション単位で SET statement_mem = '512MB'; を実行
ケース3: OSからのメモリ割り当て失敗
Out of memory. Failed on request of size ... VM Protect failed to allocate ...
原因:gp_vmem_protect_limit が物理メモリ+SWAP容量を超える設定になっている可能性あり。
対応策:OSレベルのメモリ可用性を確認し、パラメータを下方修正
ケース4: spillファイル数超過
ERROR: number of workfiles per query limit exceeded
対応策:spillファイル上限を引き上げるのではなく、まずSQL最適化・データスキュー解消・統計情報更新を実施。根本原因が解消されない限り、単なるパラメータ緩和は一時しのぎに過ぎない。
メモリ使用量の監視
実行中のセッションのメモリ消費状況は以下のビューで確認可能:
SELECT * FROM gp_toolkit.gp_session_state_memory_consumption;
一般的な最適化手順
- EXPLAIN ANALYZE で実行計画を確認し、ハッシュ結合やソートのコストを評価
- work_mem を一時的に増加(例:
SET work_mem = '1GB';)してspillを回避 - データ分布キーの見直しと再分散(ALTER TABLE ... SET DISTRIBUTED BY)
- 不要な同時実行を抑制するため、ユーザを適切なリソースキューに割り当て