Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Clustered Index による会計レポート機能のパフォーマンス改善

Clustered Index による会計レポート機能のパフォーマンス改善

Avatar for Fumiya Nakamura

Fumiya Nakamura

December 05, 2025

Other Decks in Technology

Transcript

  1.   レポート機能の仕組み 仕訳
 仕訳
 仕訳
 仕訳
 集計テーブル
 集計テーブル
 集計テーブル
 レポート


    更新のたびに
 非同期で集計
 リクエストのたびに
 同期的に集計
 仕訳

  2.   レポート機能の仕組み 仕訳
 仕訳
 仕訳
 仕訳
 集計テーブル
 集計テーブル
 集計テーブル
 レポート


    更新のたびに
 非同期で集計
 リクエストのたびに
 同期的に集計
 仕訳
 ここが遅かった

  3.   どんなクエリ? SELECT SUM(残高・発生額) FROM 集計テーブル WHERE 会計年度 = ?

    AND 勘定科目 IN (?, ..., ?) GROUP BY 会計年度, 勘定科目

  4.   どんなクエリ? SELECT SUM(残高・発生額) FROM 集計テーブル WHERE 会計年度 = ?

    AND 勘定科目 IN (?, ..., ?) GROUP BY 会計年度, 勘定科目
 ①会計年度・勘定科目で絞り込む

  5.   どんなクエリ? SELECT SUM(残高・発生額) FROM 集計テーブル WHERE 会計年度 = ?

    AND 勘定科目 IN (?, ..., ?) GROUP BY 会計年度, 勘定科目
 ②会計年度・勘定科目でグループ化

  6.   どんなクエリ? SELECT SUM(残高・発生額) FROM 集計テーブル WHERE 会計年度 = ?

    AND 勘定科目 IN (?, ..., ?) GROUP BY 会計年度, 勘定科目
 ③金額カラムを足し合わせる

  7.   EXPLAIN (MySQL) *************************** 1. row *************************** id: 1 select_type:

    SIMPLE table: 集計テーブル partitions: NULL type: ref possible_keys: <(会計年度, 勘定科目, その他)のユニークなセカンダリインデックス > key: <(会計年度, 勘定科目, その他)のユニークなセカンダリインデックス > key_len: 16 ref: const,const rows: 110164 filtered: 100.00 Extra: NULL
  8.   EXPLAIN (MySQL) *************************** 1. row *************************** id: 1 select_type:

    SIMPLE table: 集計テーブル partitions: NULL type: ref possible_keys: <(会計年度, 勘定科目, その他)のユニークなセカンダリインデックス > key: <(会計年度, 勘定科目, その他)のユニークなセカンダリインデックス > key_len: 16 ref: const,const rows: 110164 filtered: 100.00 Extra: NULL rows の値は⼤きいが、それ以外は⼀⾒すると問題なさそう
  9.   B+Tree Indexを⽤いたレコードの検索
 Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 key(Alice)
 key(Bob)
 key(Eric)
 key(Jim)
 key(Rose)
 key(Tom)
 rec(Tom)
 rec(Rose)
 rec(Eric)
 rec(Bob)
 rec(Alice)
 rec(Jim)
 実レコードへのポインタ
 実レコードの並び

  10.   B+Tree Indexを⽤いたレコードの検索
 Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 key(Alice)
 key(Bob)
 key(Eric)
 key(Jim)
 key(Rose)
 key(Tom)
 rec(Tom)
 rec(Rose)
 rec(Eric)
 rec(Bob)
 rec(Alice)
 rec(Jim)
 実レコードへのポインタ
 Eric以上Tom以下の レコードが欲しい!
 実レコードの並び

  11.   B+Tree Indexを⽤いたレコードの検索
 Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 key(Alice)
 key(Bob)
 key(Eric)
 key(Jim)
 key(Rose)
 key(Tom)
 rec(Tom)
 rec(Rose)
 rec(Eric)
 rec(Bob)
 rec(Alice)
 rec(Jim)
 実レコードへのポインタ
 実レコードの並び
 Eric以上Tom以下の レコードが欲しい!

  12.   B+Tree Indexを⽤いたレコードの検索
 Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 key(Alice)
 key(Bob)
 key(Eric)
 key(Jim)
 key(Rose)
 key(Tom)
 rec(Tom)
 rec(Rose)
 rec(Eric)
 rec(Bob)
 rec(Alice)
 rec(Jim)
 実レコードへのポインタ
 実レコードの並び
 Eric以上Tom以下の レコードが欲しい!

  13.   B+Tree Indexを⽤いたレコードの検索
 Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 key(Alice)
 key(Bob)
 key(Eric)
 key(Jim)
 key(Rose)
 key(Tom)
 rec(Tom)
 rec(Rose)
 rec(Eric)
 rec(Bob)
 rec(Alice)
 rec(Jim)
 実レコードの並び
 実レコードへのポインタ
 ディスクへのランダムアクセスに なってしまう! 
 Eric以上Tom以下の レコードが欲しい!

  14.   Clustered Index Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 key(Alice)
 key(Bob)
 key(Eric)
 key(Jim)
 key(Rose)
 key(Tom)
 rec(Alice)
 rec(Bob)
 rec(Eric)
 rec(Jim)
 rec(Rose)
 rec(Tom)
 実レコードへのポインタ
 実レコードの並び
 Eric以上Tom以下の レコードが欲しい!

  15.   Clustered Index Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 key(Alice)
 key(Bob)
 key(Eric)
 key(Jim)
 key(Rose)
 key(Tom)
 rec(Alice)
 rec(Bob)
 rec(Eric)
 rec(Jim)
 rec(Rose)
 rec(Tom)
 実レコードへのポインタ
 実レコードの並び
 Eric以上Tom以下の レコードが欲しい!

  16.   Clustered Index Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 key(Alice)
 key(Bob)
 key(Eric)
 key(Jim)
 key(Rose)
 key(Tom)
 rec(Alice)
 rec(Bob)
 rec(Eric)
 rec(Jim)
 rec(Rose)
 rec(Tom)
 実レコードへのポインタ
 ディスクへのアクセスが 
 シーケンシャルになる! 
 実レコードの並び
 Eric以上Tom以下の レコードが欲しい!

  17.   MySQLにおけるClustered Index Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 rec(Alice)
 rec(Bob)
 rec(Eric)
 rec(Jim)
 rec(Rose)
 rec(Tom)
 実レコード
 Eric以上Tom以下の レコードが欲しい!

  18.   MySQLにおけるClustered Index Alice
 Woo
 Zark
 Alice
 Eric
 Rose
 Alice


    Bob
 Eric
 Jim
 Rose
 Tom
 rec(Alice)
 rec(Bob)
 rec(Eric)
 rec(Jim)
 rec(Rose)
 rec(Tom)
 実レコード
 leaf nodeだけでクエリの結果を 返すことができる! 
 Eric以上Tom以下の レコードが欲しい!

  19.   今回のケースでClustered Indexを使⽤できるか? SELECT SUM(残高・発生額) FROM 集計テーブル WHERE 会計年度 =

    ? AND 勘定科目 IN (?, ..., ?) GROUP BY 会計年度, 勘定科目
 集計テーブルには (会計年度, 勘定科⽬, その他) のユニークなセカンダリイ ンデックスが張られている
  20.   今回のケースでClustered Indexを使⽤できるか? SELECT SUM(残高・発生額) FROM 集計テーブル WHERE 会計年度 =

    ? AND 勘定科目 IN (?, ..., ?) GROUP BY 会計年度, 勘定科目
 集計テーブルには (会計年度, 勘定科⽬, その他) のユニークなセカンダリイ ンデックスが張られている → (会計年度, 勘定科⽬, その他) を主キーとする新しいテーブルを作れば良 い
  21.   新しい集計テーブルの導⼊ 仕訳
 仕訳
 仕訳
 仕訳
 集計テーブル
 集計テーブル
 集計テーブル
 レポート


    更新のたびに
 非同期で集計
 リクエストのたびに
 同期的に集計
 仕訳

  22.   新しい集計テーブルの導⼊ 仕訳
 仕訳
 仕訳
 仕訳
 集計テーブル
 集計テーブル
 集計テーブル
 レポート


    更新のたびに
 非同期で集計
 リクエストのたびに
 同期的に集計
 仕訳
 集計テーブルV2
 集計テーブルV2
 集計テーブルV2

  23.   新しい集計テーブルの導⼊ 仕訳
 仕訳
 仕訳
 仕訳
 集計テーブル
 集計テーブル
 集計テーブル
 レポート


    更新のたびに
 非同期で集計
 リクエストのたびに
 同期的に集計
 仕訳
 集計テーブルV2
 集計テーブルV2
 集計テーブルV2
 新旧テーブルに double write し つつ、レポートの集計は新テーブ ルに切り替える