今日出てきた言葉で
「あなたはパフォーマンスチューニングの経験はありますか。」
と言われた。
なんとなく速度のことだろうなとは分かった。
そういったものは確かに経験がなかったので調べてみることにした。
メモリのチューニングやらインデックス、パーティショニングなど出てきた。
とりあえずとっつきやすそうなインデックスから調べて見直しが出来るよう超簡単にまとめてみた。
そもそもインデックスって
本のさくいんと同じ。
- カラム値 → 行位置 の対応表を別ファイルに保持
- 検索・JOIN・ORDER BY が速くなる
- 追加と更新はインデックスにも追加するためやや遅くなる
イメージ
シーン | さくいん無し | さくいん有り (インデックス) |
---|---|---|
本 | 1ページ目からパラパラめくって目的の語を探す | 後ろの索引でページ番号が “P.128” と分かり、いきなりそこへジャンプ |
DBテーブル |
SELECT * FROM users WHERE email = 'foo@example.com' → 行を最初から最後まで順番にチェック (Seq Scan) |
e-mail列にインデックスを張り、Index Scan で “foo@example.com は行 42” と目次から一発取得 |
インデックスを作成する時は下記
// migration
$table->index('email');
そうするとイメージはこうなる。
users テーブル (10万行)
id | |
---|---|
1 | a@ex.com |
2 | b@ex.com |
… | … |
索引ができているらしい。
インデックスが貼っていない場合は、行を全て確認をする。
速度の測定はEXPLAIN
で出来る。
EXPLAIN ANALYZE SELECT * FROM users WHERE email='x@ex.com';
書き込み頻度が高い列には逆に不向き?
インデックスは追加・更新時にもメンテナンスコストが発生する
索引構造は「キー → 行位置」の対応を別ファイル(あるいは別領域)に保持している。
INSERT / UPDATE / DELETE のたびに、その索引構造を再配置・再計算する。
例
1.新しいレコードを追加するとき、該当カラムのインデックスにも「新しいキー」を挿入し、木構造を再調整する。
2.値を更新するときは、古いキーを索引から削除し、新しいキーを再挿入する必要がある。
これらの操作は「データ書き込み」と「索引構造のロック/再配置」が発生するため書き込み処理全体が遅くなる。
人間の知覚における時間感覚の目安
0.1秒未満(100ms)
ほとんど「瞬時」に感じる。ユーザーは遅さを意識しない。
0.1秒~0.3秒(100ms~300ms)
「わずかな遅れ」を感じるが、ストレスにはならない。
フロントエンドのボタン押下→画面遷移などでは、このレベルなら許容されやすい。
0.3秒~1秒(300ms~1s)
もはや「遅いな」と気づく領域。
DBクエリ単位で1秒前後かかる場合や、ページ全体のレンダリングに1秒以上かかる場合はチューニングを検討したほうがよい。
1秒~3秒(1s~3s)
ユーザーは「待たされている感」を明確に感じる。
ページ遷移や一覧取得などで1~3秒かかっている場合は、かなりの確率で離脱率や操作中断が増える。緊急度が高い。
3秒以上(>3s)
ほとんどのユーザーは「重い」「ストップしている」と感じ、途中で操作をやめることも多い。
このレベルの遅延が発生する箇所はページ全体を工夫して先読みを行っても、根本的にSQLやインフラ周りの最適化が必要。
あまり意識したことがないが意外にシビヤだった。