InnoDB
構成要素
table:構成要素
構成要素 InnoDB での名前
ステーブルデータベース テーブルスペース
データベースキャッシュ バッファプール
ステーブルログ ログ
ログバッファ ログバッファ
下図は、奥野さんのスライドよりほぼ引用。
https://gyazo.com/6d721bc95a5dbc70b5cd4a4c3b45bdec
https://www.slideshare.net/nippondanji/mysql-64455514/14
インデックス
クラスタインデックス
InnoDB のインデックスはクラスタインデックス (Index Organized Table, IOT) になっている。これは、データがインデックスのリーフノード上に格納されているので、実質データも全てクラスタインデックスに含まれている。
あるテーブルのクラスタインデックス のキーには、以下が採用される (優先順位順)。
PRIMARY KEY
(はじめに現れる) NULL を含まないユニークなキー
暗黙的な ROWID (48 bit)
InnoDBでテーブルを作成すると、それは必ずクラスタインデックスとして格納される。実質InnoDBはトランザクション機能を持ったインデックスストレージである、と言える。
https://dev.mysql.com/doc/refman/5.6/ja/innodb-index-types.html
セカンダリインデックス
クラスタインデックス 以外のインデックス。リーフノードにクラスタインデックスのキーを含む。
通常、セカンダリインデックスを探索した場合、その結果取得できたキーからさらにクラスタインデックスの探索を行う必要があるため冗長だが、セカンダリインデックスの探索のみで得たい情報が全て得られ、クラスタインデックスの探索が必要ない場合がある。これをCovering Indexという。
https://dev.mysql.com/doc/refman/5.6/ja/glossary.html#glos_secondary_index
インデックスの種類
B+ツリーインデックス PRIMARY KEY, UNIQUE, INDEX 等
転置インデックス FULLTEXT インデックス。利用しているのは実質 B+ っぽい?
Rツリーインデックス 空間データ型の検索
(ハッシュインデックス) MEMORY ストレージでのみ利用でき、InnoDB では利用できない
https://dev.mysql.com/doc/refman/5.6/ja/mysql-indexes.html
効率
高速に処理されるのは、リーフノードの検索まで。ルートノードと内部ノードはキャッシュされる。また、リーフノードもデータがソートされており、隣接したインデックスは同一ブロックに格納されているため、少ない I/O で検索できる。
セカンダリインデックスを通したクラスタインデックスへのアクセスはランダムアクセスになるので、この I/O の回数を減らすことが重要。
MySQLでインデックスを使って高速化するならCovering Indexが使えそう - (゚∀゚)o彡 sasata299's blog
REDO ログ
ユーザが何らかの更新処理を行ったとき、その変更処理自体はバッファプール上で行われ、COMMIT が終了した時点でログの永続化が終了している。
一度の操作につき、かなり粒度の細かい MTR が生成され、ログバッファに書き込まれる。ログバッファは innodb_log_buffer_size で設定される。
MTR は、生成されてから (②) すぐにはログバッファへは行かず、MTR が COMMIT されて (③) はじめてログバッファに書き込まれる。また、その時点ではまだ永続化は行われず、トランザクション が COMMIT (④)、あるいはログバッファを使い果たすと、ログに永続化 (⑥) される。
InnoDB のログは WAL (Write-Ahead-Log) であり、データファイルの永続化よりも、必ずログの永続化の方が先になる(⑥ -> ⑦)。
https://gyazo.com/d005b13744ab474cfc2d495cea252c4e
WAL という性質から、あるタイミングでは、変更は行われたが永続化はされていないページ、すなわち ダーティページ が存在する。
InnoDB では、ファジーチェック という方式のチェックポイントが実装されている。この方式では、ダーティページは段階的にフラッシュする。どこまでフラッシュしたか?は、ログのヘッダに LSN (Log Sequence Number) として記録する。チェックポイントに記録された LSN より古い REDO ログは、データファイルへの永続化が行われたことがわかるため、解放できる。
LSN を解放するためには対応する ダーティページ がフラッシュされる必要がある。そのため、ダーティページ は古い方から順にフラッシュされる。論理上、チェックポイントより古いダーティページは存在しない。
https://gyazo.com/4d5fb823a5a7a44fe978b2ca786e9daa
MTR を記録しているのは、それを REDO ログ として、クラッシュリカバリ を行うため。MTR で クラッシュリカバリ を行うための制約は以下の2つ。
WAL (Write Ahead Log)
ダーティページが残っている間は、対応する MTR (REDO ログ) が消失してはならない
このような制約から、ログファイルの容量がいっぱいになると、データの永続化がサスペンドしてしまう。
MVCC
MVCC については別途記事を書いた。
InnoDB バッファープール
https://dev.mysql.com/doc/refman/5.6/ja/innodb-buffer-pool.html
https://stackoverflow.com/questions/10542853/how-to-clear-flush-mysql-innodb-buffer-pool