MySQLにおけるSQLクエリ最適化とトランザクション分離レベルの理解

セットアップ手順

MySQL接続コマンド:

mysql -u管理者 -p -h x.x.x.x -P 3306

データベースバックアップ:

mysqldump -h ホストアドレス -uユーザー名 -pパスワード database_name >/path/to/backup.sql

パフォーマンス改善手法

  1. !=<> の使用を避ける
  2. インデックスを利用する演算子:
    <,<=,=,>,>=,BETWEEN,IN,LIKE 'prefix%'
    
  3. NULL値の判定処理を避ける
  4. OR条件の使用を控える代わりに以下を使用:
    SELECT * FROM instructeur WHERE identifier = 100 UNION ALL SELECT * FROM instructeur WHERE identifier = 200
    # UNION ALLは重複レコードも含めてすべて返却し、UNIONより高速
    
  5. 前方一致のLIKE検索(LIKE '%suffix')ではなく後方一致(LIKE 'prefix%')を使用
  6. INやNOT INの代わりにBETWEENを使用する
  7. 比較演算子の左辺で計算処理を行わない
  8. 結合クエリの最適化:
    -- 手法A(非推奨)
    SELECT child.*, parent.title AS parent_title
    FROM menu_items child LEFT JOIN menu_items parent
    ON child.parent_identifier = parent.identifier
    
    -- 手法B(推奨)
    SELECT child.*, (
        SELECT parent.title
        FROM menu_items parent
        WHERE child.parent_identifier = parent.identifier
    ) AS parent_title
    FROM menu_items child
    
    -- 実際の例
    SELECT 
    professor.name, (SELECT subject.department FROM subject WHERE subject.professor_id = professor.id)
    FROM professor WHERE professor.id = 1
    

トランザクションのACID特性と分離レベル

基本特性

  • アトミシティ(Atomicity): トランザクションは分割不可能な単位として扱われ、すべて実行されるかすべて破棄されるかのいずれか
  • 整合性(Consistency): データベースは常に一貫した状態を維持し、トランザクション完了時にデータの一貫性が保たれる
  • 分離性(Isolation): 同時実行されるトランザクション間の変更は互いに影響を与えない
  • 永続性(Durability): トランザクションがコミットされたら、その変更は永続的に保存される

分離レベル(1~4で効率性が低下)

  • Read Uncommitted(未コミット読み取り): 最低レベル、保護なし
  • Read Committed(コミット済み読み取り): ダーティリード防止、Oracleのデフォルト
  • Repeatable Read(反復可能読み取り): ダーティリードとノンリピータブルリード防止、MySQLのデフォルト
  • Serializable(直列化): ダーティリード、ノンリピータブルリード、ファントムリードをすべて防止
# 分離レベル設定
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
# トランザクション処理...
COMMIT; -- または ROLLBACK;

競合現象の種類

ダーティリード(Dirty Read)

他のトランザクションによってまだコミットされていないデータを読み取ってしまう現象

ノンリピータブルリード(Non-repeatable Read)

同一トランザクション内で同じデータを複数回読み取った際に、他のトランザクションによる更新により結果が異なる現象。通常は更新(UPDATE)操作に関連する。

ファントムリード(Phantom Read)

挿入(INSERT)操作に関する現象。トランザクションAがデータを変更している間に、トランザクションBが新しいレコードを挿入してコミットすると、トランザクションAでは変更が完全に反映されていないように見える不具合が発生する。

タグ: MySQL sql-optimization transaction-isolation database-performance sql-query

7月26日 21:45 投稿