デフォルトでは、EXPLAINは監視ユーザーとして直接実行され、PostgreSQLは計画時にテーブル権限を確認します — そのため、監視ユーザーに書き込みアクセス権(本来持つべきではありません)がない限り、行ロックまたは書き込みステートメントはpermission deniedで失敗します。
EXPLAINヘルパー関数を作成する
監視ユーザーに書き込みアクセス権を付与せずに行ロックまたは書き込みステートメントのクエリ計画を収集するには、各データベースに次の関数を作成します:
CREATE OR REPLACE FUNCTION otel.explain_statement(l_query text)RETURNS jsonLANGUAGE plpgsqlSECURITY DEFINERAS $$DECLARE v_plan json; v_param_count int; v_nulls text := ''; i int;BEGIN SET TRANSACTION READ ONLY; SET plan_cache_mode = force_generic_plan;
EXECUTE 'PREPARE otel_explain_stmt AS ' || l_query;
SELECT COALESCE(array_length(parameter_types, 1), 0) INTO v_param_count FROM pg_prepared_statements WHERE name = 'otel_explain_stmt';
IF v_param_count > 0 THEN FOR i IN 1..v_param_count LOOP v_nulls := v_nulls || CASE WHEN i > 1 THEN ', ' ELSE '' END || 'null'; END LOOP; v_nulls := '(' || v_nulls || ')'; END IF;
EXECUTE 'EXPLAIN (FORMAT JSON) EXECUTE otel_explain_stmt' || v_nulls INTO v_plan; DEALLOCATE otel_explain_stmt; RETURN v_plan;EXCEPTION WHEN OTHERS THEN IF EXISTS (SELECT 1 FROM pg_prepared_statements WHERE name = 'otel_explain_stmt') THEN DEALLOCATE otel_explain_stmt; END IF; RAISE;END;$$;
GRANT EXECUTE ON FUNCTION otel.explain_statement(text) TO <YOUR_DB_USERNAME>;実行計画の収集メカニズム
- レート制限:
top_query_collection.max_explain_each_interval(デフォルトは1000)は、スクレイプあたりのEXPLAINを制限します。 - キャッシング:
query_plan_cache_size/query_plan_cache_ttl(デフォルトは1000エントリ/1h)は、取得した計画をクエリIDをキーとしてキャッシュします。