OLTP Anti-Patterns

一部のコンテンツは LLM によって生成されており、まだ手動で検証されていません。

OLTP(Online Transaction Processing)システムの一般的(いっぱんてき) なアンチパターンとベストプラクティス。

  flowchart LR
    subgraph Bad["アンチパターン"]
        A[逐次処理]
        B[長いトランザクション]
        C[フルテーブルスキャン]
    end
    subgraph Good["ベストプラクティス"]
        D[バッチ処理]
        E[短いトランザクション]
        F[インデックス検索]
    end
    A -.-> D
    B -.-> E
    C -.-> F

クエリ効率

アンチパターン問題(もんだい)ベストプラクティス
DML 入れ子(いれこ) クエリ毎回(まいかい) サブクエリを実行(じっこう)性能(せいのう)非常(ひじょう)(わる)JOINを使用(しよう) または事前(じぜん) クエリ() バッチ処理(しょり)
逐次(ちくじ) カーソル処理(しょり)大量(たいりょう) データの(ぎょう) 単位(たんい) 処理(しょり)効率(こうりつ)(ひく)バッチ操作(そうさ) またはset-basedロジック
過度(かど)動的(どうてき) SQL最適化(さいてきか) 困難(こんなん) 、SQLインジェクションの危険(きけん)パラメータ() クエリと準備(じゅんび) () みステートメント
DML 入れ子クエリの例

アンチパターン:

UPDATE orders
SET status = 'processed'
WHERE customer_id IN (
    SELECT id FROM customers WHERE region = 'APAC'
);
-- サブクエリは毎回customersテーブルをスキャン

ベストプラクティス:

-- JOINを使用
UPDATE orders o
JOIN customers c ON o.customer_id = c.id
SET o.status = 'processed'
WHERE c.region = 'APAC';
カーソル処理 vs バッチ操作

アンチパターン(逐次(ちくじ) 処理(しょり) ):

DECLARE cur CURSOR FOR SELECT id FROM orders WHERE status = 'pending';
OPEN cur;
FETCH NEXT FROM cur INTO @id;
WHILE @@FETCH_STATUS = 0
BEGIN
    UPDATE orders SET status = 'processing' WHERE id = @id;
    FETCH NEXT FROM cur INTO @id;
END;

ベストプラクティス(バッチ処理(しょり) ):

UPDATE orders SET status = 'processing' WHERE status = 'pending';

トランザクション管理

アンチパターン問題(もんだい)ベストプラクティス
大量(たいりょう) データ単一(たんいつ) トランザクションロック保持(ほじ) 時間(じかん)(なが) い、undo log膨張(ぼうちょう)分割(ぶんかつ) コミット、(かく) バッチの件数(けんすう)制御(せいぎょ)
無効(むこう) なトランザクション境界(きょうかい)ビジネスロジックが(ただ) しくトランザクションに(ふく) まれていないトランザクション範囲(はんい)分離(ぶんり) レベルを明確(めいかく)定義(ていぎ)
バッチ処理(しょり)使用(しよう) しない大量(たいりょう) INSERT/UPDATEを逐次(ちくじ) 実行(じっこう)bulk insert、batch updateを使用(しよう)
分割コミットの例

アンチパターン:

BEGIN TRANSACTION;
DELETE FROM logs WHERE created_at < '2020-01-01';
-- 数百万行に影響、ロック時間が長すぎる
COMMIT;

ベストプラクティス:

WHILE EXISTS (SELECT 1 FROM logs WHERE created_at < '2020-01-01')
BEGIN
    BEGIN TRANSACTION;
    DELETE TOP (10000) FROM logs WHERE created_at < '2020-01-01';
    COMMIT;
END;

インデックス設計

アンチパターン問題(もんだい)ベストプラクティス
インデックス不足(ふそく)頻繁(ひんぱん) なフルテーブルスキャン、クエリが(おそ)クエリパターンに(もと) づいて適切(てきせつ) なインデックスを作成(さくせい)
過度(かど) なインデックス()()性能(せいのう) 低下(ていか)維持(いじ) コスト(たか)インデックス使用率(しようりつ)定期的(ていきてき)確認(かくにん)冗長(じょうちょう) なものを削除(さくじょ)
過度(かど)正規化(せいきか)頻繁(ひんぱん) なJOINが性能(せいのう)影響(えいきょう)適度(てきど)非正規化(ひせいきか) またはマテリアライズドビュー
インデックス設計の考慮事項

インデックス要件(ようけん)評価(ひょうか)

-- スロークエリの確認
SELECT * FROM sys.dm_exec_query_stats
ORDER BY total_elapsed_time DESC;

-- 欠落インデックスの提案を確認(SQL Server)
SELECT * FROM sys.dm_db_missing_index_details;

-- 未使用インデックスの確認
SELECT * FROM sys.dm_db_index_usage_stats
WHERE user_seeks = 0 AND user_scans = 0;

複合(ふくごう) インデックスの順序(じゅんじょ) 原則(げんそく)

  • 選択性(せんたくせい)(たか)(れつ)(さき)

  • WHERE条件(じょうけん)頻繁(ひんぱん)使用(しよう) される(れつ)優先(ゆうせん)

  • カバリングインデックスを検討(けんとう)

その他の問題

アンチパターン問題(もんだい)ベストプラクティス
トリガーの乱用(らんよう)ビジネスロジックの隠蔽(いんぺい) 、デバッグ困難(こんなん)性能(せいのう) 問題(もんだい)ロジックをアプリケーション(そう) または明示的(めいじてき) なstored procedureに移行(いこう)
トリガーの適切な使用場面

トリガーの使用(しよう)(てき) した場面(ばめん)

  • 監査(かんさ) ログ(audit logging)

  • タイムスタンプの自動(じどう) 更新(こうしん)

  • データ整合性(せいごうせい)強制(きょうせい)制約(せいやく)実現(じつげん) できない場合(ばあい)

トリガーを() けるべき場面(ばめん)

  • 複雑(ふくざつ) なビジネスロジック

  • 複数(ふくすう) テーブルにまたがる連鎖(れんさ) 更新(こうしん)

  • トランザクション制御(せいぎょ)必要(ひつよう)操作(そうさ)