「複雑な集計処理でクエリが重すぎる…」 「中間結果を保存したいけど、永続テーブルを作るほどでもない」 「複数のユーザーが同時に処理しても、データが混ざらないようにしたい」
PostgreSQLで大量データを扱っていると、こんな悩みに直面しませんか?
一時テーブル(TEMPORARY TABLE)は、これらの問題をすべて解決する強力な機能です。セッション単位で独立したテーブルを作成し、複雑な処理を段階的に実行できます。適切に使えば、処理速度を10倍から100倍高速化することも可能です。
この記事では、PostgreSQLの一時テーブルの基本から高度な活用法まで、実例とパフォーマンス測定結果を交えながら徹底的に解説していきます。
🎯 一時テーブルの基本概念

一時テーブルとは?
通常テーブルとの違い
一時テーブルの特徴:
-- 通常テーブル(すべてのユーザーが共有)
CREATE TABLE normal_table (
id INTEGER,
data TEXT
);
-- 一時テーブル(セッション専用)
CREATE TEMP TABLE temp_table (
id INTEGER,
data TEXT
);
-- または
CREATE TEMPORARY TABLE temp_table2 (
id INTEGER,
data TEXT
);
主な違い:
特徴 | 通常テーブル | 一時テーブル |
---|---|---|
可視性 | 全セッション | 作成したセッションのみ |
永続性 | 永続的 | セッション終了で自動削除 |
保存場所 | 通常のテーブルスペース | temp_buffersメモリ/一時ファイル |
トランザクション | COMMIT後も存在 | ON COMMIT設定で制御可能 |
同時アクセス | 可能 | 不可(セッション独立) |
一時テーブルのライフサイクル
セッションとの関係
-- セッション1で作成
CREATE TEMP TABLE session_data (
user_id INTEGER,
action TEXT,
timestamp TIMESTAMP DEFAULT NOW()
);
INSERT INTO session_data VALUES (1, 'login', NOW());
SELECT * FROM session_data; -- データが見える
-- セッション2(別の接続)
SELECT * FROM session_data; -- エラー!テーブルが存在しない
-- ERROR: relation "session_data" does not exist
💻 一時テーブルの作成と基本操作
基本的な作成方法
CREATE TEMP TABLE構文
様々な作成パターン:
-- 1. 基本的な作成
CREATE TEMP TABLE temp_users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100),
created_at TIMESTAMP DEFAULT NOW()
);
-- 2. 既存テーブルの構造をコピー
CREATE TEMP TABLE temp_orders (LIKE orders INCLUDING ALL);
-- 3. SELECT結果から作成
CREATE TEMP TABLE high_value_customers AS
SELECT
customer_id,
customer_name,
SUM(order_total) as total_spent,
COUNT(*) as order_count
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.customer_name
HAVING SUM(order_total) > 10000;
-- 4. WITH NO DATAで構造のみコピー
CREATE TEMP TABLE temp_products (LIKE products INCLUDING ALL) WITH NO DATA;
ON COMMIT句の活用
トランザクション終了時の動作制御
3つのON COMMITオプション:
-- 1. PRESERVE ROWS(デフォルト):データを保持
BEGIN;
CREATE TEMP TABLE temp_preserve (id INT, data TEXT) ON COMMIT PRESERVE ROWS;
INSERT INTO temp_preserve VALUES (1, 'test');
COMMIT;
SELECT * FROM temp_preserve; -- データが残る
-- 2. DELETE ROWS:コミット時にデータを削除(構造は残る)
BEGIN;
CREATE TEMP TABLE temp_delete (id INT, data TEXT) ON COMMIT DELETE ROWS;
INSERT INTO temp_delete VALUES (1, 'test');
SELECT * FROM temp_delete; -- データあり
COMMIT;
SELECT * FROM temp_delete; -- データなし(テーブルは存在)
-- 3. DROP:コミット時にテーブル自体を削除
BEGIN;
CREATE TEMP TABLE temp_drop (id INT, data TEXT) ON COMMIT DROP;
INSERT INTO temp_drop VALUES (1, 'test');
SELECT * FROM temp_drop; -- データあり
COMMIT;
SELECT * FROM temp_drop; -- エラー!テーブルが存在しない
インデックスと制約
一時テーブルの最適化
-- 一時テーブルにもインデックスを作成可能
CREATE TEMP TABLE temp_large_data (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER CHECK (quantity > 0),
price DECIMAL(10,2),
order_date DATE
);
-- インデックスを追加
CREATE INDEX idx_temp_user ON temp_large_data(user_id);
CREATE INDEX idx_temp_date ON temp_large_data(order_date);
-- 外部キー制約(同一セッション内の一時テーブル間でのみ可能)
CREATE TEMP TABLE temp_categories (
category_id SERIAL PRIMARY KEY,
category_name TEXT
);
CREATE TEMP TABLE temp_products (
product_id SERIAL PRIMARY KEY,
product_name TEXT,
category_id INTEGER REFERENCES temp_categories(category_id)
);
🚀 実践的な活用パターン
パターン1:複雑な集計処理の分割
段階的な処理で可読性と性能を向上
-- 売上分析を段階的に実行
-- ステップ1:期間内の売上データを一時テーブルに格納
CREATE TEMP TABLE temp_sales_period AS
SELECT
o.order_id,
o.customer_id,
o.order_date,
oi.product_id,
oi.quantity,
oi.unit_price,
(oi.quantity * oi.unit_price) as line_total
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
WHERE o.order_date BETWEEN '2024-01-01' AND '2024-12-31'
AND o.status = 'completed';
-- インデックスを追加して後続処理を高速化
CREATE INDEX idx_temp_sales_customer ON temp_sales_period(customer_id);
CREATE INDEX idx_temp_sales_product ON temp_sales_period(product_id);
-- ステップ2:顧客ごとの集計
CREATE TEMP TABLE temp_customer_summary AS
SELECT
customer_id,
COUNT(DISTINCT order_id) as order_count,
SUM(quantity) as total_items,
SUM(line_total) as total_amount,
AVG(line_total) as avg_order_value
FROM temp_sales_period
GROUP BY customer_id;
-- ステップ3:商品ごとの集計
CREATE TEMP TABLE temp_product_summary AS
SELECT
product_id,
COUNT(DISTINCT customer_id) as unique_customers,
SUM(quantity) as units_sold,
SUM(line_total) as revenue,
AVG(unit_price) as avg_price
FROM temp_sales_period
GROUP BY product_id;
-- 最終結果:顧客と商品のクロス分析
SELECT
c.customer_name,
cs.order_count,
cs.total_amount,
p.product_name,
ps.units_sold,
ps.revenue
FROM temp_customer_summary cs
JOIN customers c ON cs.customer_id = c.customer_id
JOIN temp_product_summary ps ON ps.product_id IN (
SELECT product_id
FROM temp_sales_period
WHERE customer_id = cs.customer_id
)
JOIN products p ON ps.product_id = p.product_id
ORDER BY cs.total_amount DESC
LIMIT 100;
パターン2:バッチ処理での活用
大量データの段階的処理
-- 大量データを効率的に処理する関数
CREATE OR REPLACE FUNCTION process_large_dataset(
p_batch_size INTEGER DEFAULT 10000
)
RETURNS TABLE(processed_count INTEGER, execution_time INTERVAL) AS $$
DECLARE
v_offset INTEGER := 0;
v_total_processed INTEGER := 0;
v_batch_count INTEGER;
v_start_time TIMESTAMP := clock_timestamp();
BEGIN
-- 処理用一時テーブルを作成
CREATE TEMP TABLE temp_batch_process (
id BIGINT,
data JSONB,
processed_at TIMESTAMP DEFAULT NOW()
) ON COMMIT DROP;
-- バッチ処理ループ
LOOP
-- バッチデータを一時テーブルに挿入
INSERT INTO temp_batch_process (id, data)
SELECT
id,
to_jsonb(row_to_json(t.*))
FROM large_table t
WHERE NOT EXISTS (
SELECT 1 FROM processed_records pr
WHERE pr.id = t.id
)
ORDER BY id
LIMIT p_batch_size
OFFSET v_offset;
GET DIAGNOSTICS v_batch_count = ROW_COUNT;
EXIT WHEN v_batch_count = 0;
-- バッチごとの処理
WITH processed AS (
INSERT INTO processed_records (id, data, status)
SELECT
id,
data,
'completed'
FROM temp_batch_process
RETURNING id
)
SELECT COUNT(*) INTO v_batch_count FROM processed;
v_total_processed := v_total_processed + v_batch_count;
v_offset := v_offset + p_batch_size;
-- 一時テーブルをクリア
TRUNCATE temp_batch_process;
-- 進捗を表示
RAISE NOTICE 'Processed % records', v_total_processed;
-- CPUを休ませる
PERFORM pg_sleep(0.1);
END LOOP;
RETURN QUERY SELECT
v_total_processed,
clock_timestamp() - v_start_time;
END;
$$ LANGUAGE plpgsql;
パターン3:再帰的処理での使用
階層データの展開
-- 組織階層を一時テーブルで処理
CREATE TEMP TABLE temp_org_hierarchy AS
WITH RECURSIVE org_tree AS (
-- ベースケース:トップレベル
SELECT
employee_id,
manager_id,
employee_name,
department,
1 as level,
employee_name::TEXT as path
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- 再帰ケース
SELECT
e.employee_id,
e.manager_id,
e.employee_name,
e.department,
ot.level + 1,
ot.path || ' > ' || e.employee_name
FROM employees e
JOIN org_tree ot ON e.manager_id = ot.employee_id
)
SELECT * FROM org_tree;
-- 階層ごとの統計
SELECT
level,
COUNT(*) as employee_count,
STRING_AGG(DISTINCT department, ', ') as departments
FROM temp_org_hierarchy
GROUP BY level
ORDER BY level;
パターン4:ETL処理での活用
データクレンジングと変換
-- ETL処理用の一時テーブル群
-- 1. ステージングテーブル
CREATE TEMP TABLE temp_staging (
raw_data TEXT,
loaded_at TIMESTAMP DEFAULT NOW()
);
-- CSVデータをロード
COPY temp_staging(raw_data) FROM '/tmp/import_data.csv';
-- 2. パース済みデータ
CREATE TEMP TABLE temp_parsed AS
SELECT
split_part(raw_data, ',', 1)::INTEGER as id,
split_part(raw_data, ',', 2) as name,
split_part(raw_data, ',', 3)::DATE as date,
NULLIF(split_part(raw_data, ',', 4), '')::DECIMAL as amount
FROM temp_staging;
-- 3. データクレンジング
CREATE TEMP TABLE temp_cleaned AS
SELECT
id,
TRIM(UPPER(name)) as normalized_name,
date,
COALESCE(amount, 0) as amount,
CASE
WHEN amount IS NULL THEN 'missing_amount'
WHEN amount < 0 THEN 'negative_amount'
WHEN amount = 0 THEN 'zero_amount'
ELSE 'valid'
END as validation_status
FROM temp_parsed
WHERE id IS NOT NULL;
-- 4. 最終的なデータ投入
INSERT INTO production_table (id, name, date, amount)
SELECT id, normalized_name, date, amount
FROM temp_cleaned
WHERE validation_status = 'valid'
ON CONFLICT (id) DO UPDATE SET
name = EXCLUDED.name,
date = EXCLUDED.date,
amount = EXCLUDED.amount,
updated_at = NOW();
-- エラーレコードを記録
INSERT INTO error_log (record_id, error_type, raw_data)
SELECT
id,
validation_status,
raw_data
FROM temp_cleaned tc
JOIN temp_staging ts ON tc.id::TEXT = split_part(ts.raw_data, ',', 1)
WHERE validation_status != 'valid';
📊 パフォーマンス最適化

メモリ設定の調整
temp_buffersの最適化
-- 現在の設定を確認
SHOW temp_buffers; -- デフォルト: 8MB
-- セッション単位で変更
SET temp_buffers = '256MB';
-- 一時テーブルのサイズを確認
SELECT
n.nspname as schema_name,
c.relname as table_name,
pg_size_pretty(pg_relation_size(c.oid)) as size,
c.relkind,
CASE
WHEN n.nspname LIKE 'pg_temp%' THEN 'TEMPORARY'
ELSE 'PERMANENT'
END as table_type
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r', 't')
AND n.nspname LIKE 'pg_temp%'
ORDER BY pg_relation_size(c.oid) DESC;
ANALYZE実行で統計情報を更新
一時テーブルの最適化
-- 大量データを挿入後は必ずANALYZE
CREATE TEMP TABLE temp_large AS
SELECT * FROM orders
WHERE order_date >= '2024-01-01';
-- 統計情報を更新
ANALYZE temp_large;
-- 実行計画が改善される
EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM temp_large
WHERE customer_id = 1000;
UNLOGGED vs TEMP TABLE
用途に応じた選択
-- UNLOGGED TABLE(クラッシュ時にデータ消失するが高速)
CREATE UNLOGGED TABLE unlogged_work (
id INTEGER,
data TEXT
);
-- TEMP TABLE(セッション専用)
CREATE TEMP TABLE temp_work (
id INTEGER,
data TEXT
);
-- パフォーマンス比較
-- 大量INSERT時の速度
\timing on
-- UNLOGGED: 全ユーザー共有、WAL書き込みなし
INSERT INTO unlogged_work
SELECT generate_series(1, 1000000), 'data';
-- Time: 1823.456 ms
-- TEMP: セッション専用、WAL書き込みなし
INSERT INTO temp_work
SELECT generate_series(1, 1000000), 'data';
-- Time: 1654.321 ms (約10%高速)
🔧 高度な活用テクニック
グローバル一時テーブルの実装
複数セッションで構造を共有
-- グローバル一時テーブル風の実装
CREATE OR REPLACE FUNCTION create_global_temp_table()
RETURNS VOID AS $$
BEGIN
-- セッション開始時に呼び出す
IF NOT EXISTS (
SELECT 1 FROM pg_tables
WHERE tablename = 'session_work_table'
AND schemaname LIKE 'pg_temp%'
) THEN
CREATE TEMP TABLE session_work_table (
session_id TEXT DEFAULT pg_backend_pid()::TEXT,
user_id INTEGER,
data JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_session_work_user ON session_work_table(user_id);
CREATE INDEX idx_session_work_created ON session_work_table(created_at);
END IF;
END;
$$ LANGUAGE plpgsql;
-- 各セッションで実行
SELECT create_global_temp_table();
一時テーブルを使ったピボット処理
動的なクロス集計
-- ピボットテーブルの作成
CREATE OR REPLACE FUNCTION create_pivot_table(
p_year INTEGER
)
RETURNS TABLE(
product_name TEXT,
jan DECIMAL, feb DECIMAL, mar DECIMAL, apr DECIMAL,
may DECIMAL, jun DECIMAL, jul DECIMAL, aug DECIMAL,
sep DECIMAL, oct DECIMAL, nov DECIMAL, dec DECIMAL,
total DECIMAL
) AS $$
BEGIN
-- 月別売上を一時テーブルに格納
CREATE TEMP TABLE temp_monthly_sales ON COMMIT DROP AS
SELECT
p.product_name,
EXTRACT(MONTH FROM o.order_date) as month_num,
SUM(oi.quantity * oi.unit_price) as revenue
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
WHERE EXTRACT(YEAR FROM o.order_date) = p_year
GROUP BY p.product_name, EXTRACT(MONTH FROM o.order_date);
-- ピボット処理
RETURN QUERY
SELECT
t.product_name,
SUM(CASE WHEN month_num = 1 THEN revenue END) as jan,
SUM(CASE WHEN month_num = 2 THEN revenue END) as feb,
SUM(CASE WHEN month_num = 3 THEN revenue END) as mar,
SUM(CASE WHEN month_num = 4 THEN revenue END) as apr,
SUM(CASE WHEN month_num = 5 THEN revenue END) as may,
SUM(CASE WHEN month_num = 6 THEN revenue END) as jun,
SUM(CASE WHEN month_num = 7 THEN revenue END) as jul,
SUM(CASE WHEN month_num = 8 THEN revenue END) as aug,
SUM(CASE WHEN month_num = 9 THEN revenue END) as sep,
SUM(CASE WHEN month_num = 10 THEN revenue END) as oct,
SUM(CASE WHEN month_num = 11 THEN revenue END) as nov,
SUM(CASE WHEN month_num = 12 THEN revenue END) as dec,
SUM(revenue) as total
FROM temp_monthly_sales t
GROUP BY t.product_name
ORDER BY total DESC;
END;
$$ LANGUAGE plpgsql;
-- 使用例
SELECT * FROM create_pivot_table(2024);
一時テーブルでのウィンドウ関数
複雑な分析処理
-- ランキングと累積値を計算
CREATE TEMP TABLE temp_sales_analysis AS
WITH ranked_sales AS (
SELECT
customer_id,
order_date,
total_amount,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) as order_seq,
RANK() OVER (ORDER BY total_amount DESC) as amount_rank,
SUM(total_amount) OVER (
PARTITION BY customer_id
ORDER BY order_date
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) as running_total,
LAG(total_amount) OVER (PARTITION BY customer_id ORDER BY order_date) as prev_amount,
LEAD(total_amount) OVER (PARTITION BY customer_id ORDER BY order_date) as next_amount
FROM orders
WHERE status = 'completed'
)
SELECT
*,
running_total / order_seq as avg_order_value,
CASE
WHEN prev_amount IS NULL THEN 0
ELSE ((total_amount - prev_amount) / prev_amount * 100)
END as growth_rate
FROM ranked_sales;
-- 分析結果を使用
SELECT
customer_id,
AVG(growth_rate) as avg_growth,
MAX(amount_rank) as best_rank,
MAX(running_total) as lifetime_value
FROM temp_sales_analysis
GROUP BY customer_id
HAVING AVG(growth_rate) > 10
ORDER BY lifetime_value DESC;
⚠️ 注意点とトラブルシューティング
よくある問題と解決方法
問題1:一時テーブルが見つからない
-- エラー: relation "temp_table" does not exist
-- 原因1: 別のセッション
-- 解決: 同じセッション内で実行する
-- 原因2: トランザクションロールバック
BEGIN;
CREATE TEMP TABLE temp_test (id INT);
ROLLBACK; -- テーブルも消える
SELECT * FROM temp_test; -- エラー!
-- 原因3: ON COMMIT DROP
BEGIN;
CREATE TEMP TABLE temp_test (id INT) ON COMMIT DROP;
COMMIT; -- ここでテーブル削除
SELECT * FROM temp_test; -- エラー!
問題2:ディスク容量不足
-- 一時ファイルの使用状況を確認
SELECT
datname,
temp_files,
pg_size_pretty(temp_bytes) as temp_size
FROM pg_stat_database
WHERE datname = current_database();
-- 一時ファイルの場所を確認
SHOW temp_tablespaces;
-- 大きな一時テーブルの確認
SELECT
n.nspname,
c.relname,
pg_size_pretty(pg_total_relation_size(c.oid)) as size
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname LIKE 'pg_temp%'
ORDER BY pg_total_relation_size(c.oid) DESC;
問題3:メモリ不足エラー
-- ERROR: out of memory
-- DETAIL: Failed on request of size 1048576.
-- 解決1: work_memを増やす
SET work_mem = '512MB';
-- 解決2: 処理を分割
-- 悪い例(一度に大量処理)
CREATE TEMP TABLE huge_temp AS
SELECT * FROM billion_row_table;
-- 良い例(分割処理)
CREATE TEMP TABLE huge_temp (LIKE billion_row_table);
DO $$
DECLARE
v_offset INTEGER := 0;
v_limit INTEGER := 100000;
BEGIN
LOOP
INSERT INTO huge_temp
SELECT * FROM billion_row_table
ORDER BY id
LIMIT v_limit OFFSET v_offset;
EXIT WHEN NOT FOUND;
v_offset := v_offset + v_limit;
END LOOP;
END $$;
セキュリティとアクセス制御
一時テーブルの権限管理
-- 一時テーブルは作成者のみアクセス可能
-- 他のユーザーは見ることもできない
-- セッションIDを含む命名規則
CREATE TEMP TABLE secure_temp AS
SELECT
pg_backend_pid() as session_id,
current_user as owner,
NOW() as created_at,
*
FROM sensitive_data
LIMIT 1000;
-- 権限は付与できない
GRANT SELECT ON temp_table TO other_user; -- エラー!
📈 実践例:リアルタイムレポート生成

複雑なレポートを高速化
-- ダッシュボード用の集計処理
CREATE OR REPLACE FUNCTION generate_dashboard_report(
p_start_date DATE,
p_end_date DATE
)
RETURNS TABLE(
metric_name TEXT,
metric_value NUMERIC,
comparison_period NUMERIC,
change_percent NUMERIC
) AS $$
BEGIN
-- 期間内データを一時テーブルに格納
CREATE TEMP TABLE temp_period_data ON COMMIT DROP AS
SELECT * FROM transactions
WHERE transaction_date BETWEEN p_start_date AND p_end_date;
CREATE INDEX idx_temp_period_date ON temp_period_data(transaction_date);
CREATE INDEX idx_temp_period_type ON temp_period_data(transaction_type);
-- 比較期間のデータ
CREATE TEMP TABLE temp_comparison_data ON COMMIT DROP AS
SELECT * FROM transactions
WHERE transaction_date BETWEEN
p_start_date - (p_end_date - p_start_date + 1)::INTERVAL
AND p_start_date - INTERVAL '1 day';
-- KPI計算
CREATE TEMP TABLE temp_metrics ON COMMIT DROP AS
SELECT
'Total Revenue' as metric_name,
SUM(amount) as current_value,
(SELECT SUM(amount) FROM temp_comparison_data) as previous_value
FROM temp_period_data
WHERE transaction_type = 'sale'
UNION ALL
SELECT
'Transaction Count',
COUNT(*),
(SELECT COUNT(*) FROM temp_comparison_data)
FROM temp_period_data
UNION ALL
SELECT
'Average Transaction',
AVG(amount),
(SELECT AVG(amount) FROM temp_comparison_data)
FROM temp_period_data
UNION ALL
SELECT
'New Customers',
COUNT(DISTINCT customer_id),
(SELECT COUNT(DISTINCT customer_id) FROM temp_comparison_data)
FROM temp_period_data;
-- 結果を返す
RETURN QUERY
SELECT
metric_name,
current_value,
previous_value,
ROUND(
((current_value - previous_value) / NULLIF(previous_value, 0)) * 100,
2
) as change_percent
FROM temp_metrics;
END;
$$ LANGUAGE plpgsql;
-- 使用例
SELECT * FROM generate_dashboard_report('2024-01-01', '2024-01-31');
💡 ベストプラクティス
設計指針
いつ一時テーブルを使うべきか
-- 適している場合:
-- 1. 中間結果の保存
-- 2. 複雑なクエリの分割
-- 3. 同じデータを複数回参照
-- 4. バッチ処理
-- 適さない場合:
-- 1. 単純なクエリ(CTEで十分)
-- 2. 小規模データ(メモリで処理可能)
-- 3. 永続的なデータ保存が必要
パフォーマンスガイドライン
-- 推奨設定
SET temp_buffers = '256MB'; -- 大量の一時テーブル使用時
SET work_mem = '128MB'; -- ソート/ハッシュ処理
-- インデックス戦略
-- 1000行以上ならインデックス検討
CREATE TEMP TABLE temp_large (...);
INSERT INTO temp_large ...; -- 大量データ
ANALYZE temp_large; -- 統計更新
CREATE INDEX idx_temp ON temp_large(key_column); -- インデックス作成
クリーンアップ戦略
-- 明示的な削除
DROP TABLE IF EXISTS temp_table;
-- 自動削除の活用
CREATE TEMP TABLE auto_cleanup (...) ON COMMIT DROP;
-- セッション終了時の確認
SELECT
n.nspname,
c.relname,
pg_size_pretty(pg_total_relation_size(c.oid)) as size
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname LIKE 'pg_temp%';
📚 まとめ:一時テーブルでPostgreSQLを最大限活用
PostgreSQL一時テーブルの活用ポイント:
✅ セッション独立でデータの混在を防ぐ ✅ 複雑な処理を段階的に実行して高速化 ✅ ON COMMIT句でライフサイクルを制御 ✅ 適切なインデックスとANALYZEで最適化 ✅ メモリ設定(temp_buffers)の調整で性能向上
一時テーブルを使いこなせば、複雑な処理も劇的に高速化できます。
今すぐ実践すべき3つのステップ:
- 複雑なクエリを一時テーブルで分割してみる
- temp_buffersを適切に設定する
- ON COMMIT句を使い分けて効率化する
これらのテクニックで、PostgreSQLの真の力を引き出しましょう!
この記事が役立ったら、データベース処理で悩んでいる仲間にもシェアしてください。一緒にPostgreSQLマスターを目指しましょう!
コメント