SQLでなければINSERT、あればUPDATEする実装方法とパフォーマンス

データベース操作でよく使う「なければINSERT、あればUPDATE」の実装パターンを解説します。各DBMSの特徴や実装方法の違いを比較しながら、最適な方法を探ってみませんか?

SQLでなければINSERT、あればUPDATEを実装する

この記事のポイント
📝
実装方法の種類

MySQLとPostgreSQLそれぞれの実装方法を解説

パフォーマンス比較

各実装方法のメリット・デメリットを詳しく解説

💡
最適な使い分け

ケースに応じた実装方法の選び方を紹介

MySQLでのINSERT ON DUPLICATE KEY UPDATE実装

MySQLでは、INSERT ... ON DUPLICATE KEY UPDATE構文を使用することで、1つのクエリで「なければINSERT、あればUPDATE」を実現できます。


INSERT INTO users (id, name, age) 
VALUES (1, 'yamada', 25)
ON DUPLICATE KEY UPDATE 
name = VALUES(name),
age = VALUES(age)

 

この構文を使用する際の注意点として、以下が挙げられます:

  • 対象のカラムにUNIQUE制約またはPRIMARY KEY制約が必要です
  • 自動採番カラムの挙動に注意が必要です
  • 複数レコードの一括処理にも対応しています

PostgreSQLのUPSERT機能による実装方法

PostgreSQL 9.5以降では、INSERT ON CONFLICT構文(UPSERT)を使用できます。


INSERT INTO test_table (id, name)
VALUES (1, 'tanaka')
ON CONFLICT (id)
DO UPDATE SET name = EXCLUDED.name

 

このUPSERT機能の特徴は:

  • シンプルな構文で実装可能
  • トランザクションの整合性が保証される
  • パフォーマンスが優れている

複数レコードの一括処理とパフォーマンス最適化

大量データを処理する場合、パフォーマンスを考慮した実装が重要です。


-- バッチ処理の例
INSERT INTO users (id, name, age)
VALUES 
(1, 'suzuki', 30),
(2, 'tanaka', 25),
(3, 'sato', 35)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
age = VALUES(age)

 

パフォーマンス最適化のポイント:

  • インデックスの更新回数を最小限に抑える
  • 更新するカラムは必要最小限にする
  • トランザクションの範囲を適切に設定する

データベース非依存の実装パターン

データベースに依存しない実装方法として、以下のアプローチがあります:


-- テンポラリテーブルを使用した実装例
CREATE TEMPORARY TABLE temp_users AS 
SELECT * FROM users WHERE 1=0
-- データ投入
INSERT INTO temp_users VALUES (...)
-- 更新処理
UPDATE users u
SET name = t.name, age = t.age
FROM temp_users t
WHERE u.id = t.id
-- 新規データの挿入
INSERT INTO users
SELECT t.*
FROM temp_users t
LEFT JOIN users u ON t.id = u.id
WHERE u.id IS NULL

トランザクション制御とエラーハンドリング

データの整合性を保つために、適切なトランザクション制御とエラーハンドリングが必要です。


BEGIN TRANSACTION
SAVEPOINT upsert_point
BEGIN TRY
    -- UPSERT処理
    INSERT INTO users ...
    ON DUPLICATE KEY UPDATE ...
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    ROLLBACK TO SAVEPOINT upsert_point
    -- エラーログの記録
    INSERT INTO error_logs ...
    THROW
END CATCH

 

主なエラーパターンと対処方法:

  • 一意制約違反
  • デッドロック
  • タイムアウト
  • 外部キー制約違反