MySQL (InnoDB) における行のサイズと速度の関係について
集約演算を行うケースでは、行のサイズを小さく保つことはとても重要。アクセス頻度が低いコラムは別テーブルに追い出すとかしたほうがいいくらい。
一方、集約演算を行わないケース (単一行の insert, update 等を含む) の場合は、(クライアントとの通信のための) システムコールがオーバーヘッドになるので、小さなテーブルにたくさんアクセスをするよりも、長い行を持つテーブルに1回アクセスするほうが良い。
たとえば手元の環境での insert on duplicate key update の速度は、
行のサイズ | 必要時間 |
0KB | 1 |
3KB | 4 |
6KB | 7 |
9KB | 13 |
12KB | 13 |
とかそんな感じ (環境やクエリによる変わるので自分で測定してね。9KB の速度低下はページサイズの1/2を超えたからかな)。つまり、行のサイズが1KB程度だと、通信のオーバーヘッドが大きいからあまり問題にならない。
まとめておくと、最適化されたテーブル設計の基本は、
- できるだけ少数の SQL クエリでアクセス可能にする
- 高速にアクセスできるようテーブル分割をする
という順序。多数の SQL クエリを投げるのは、一般的に間違った戦略。それよりは MySQL 内で join させたほうが良い。
2/11 追記: id:lethevert さんが書いてらっしゃるように、アクセス頻度によってテーブルを分割したりインデックスを設定したりすることで、HDD へのアクセスを最小化することが必要なのは、言うまでもありません (データベースのレコードサイズ - lethevert is a programmer) 。自分が扱ってるのが、大部分がオンメモリなデータベースだったので触れるのを忘れていましたorz id:lethevert++