「N+1問題」を調べたら「N-1ロケット」がわかった話
承前
初めてリレーショナルデータベースというかMySQLを使い始めたのは、1999年5月頃、早くても4月の後半頃だったはず。
それまでは、CかPerlでCGI作ってたもののプロセスのforkがボトルネックだったので、ApacheのモジュールでHTML内にプログラムを埋め込んで処理できるものとして最も早くリリースされたmod_phpを使うことにして、Linux(1.2系?)+Apache(1系)+MySQL(3系?)+PHP(3系)=LAMP と後に呼ばれる構成で開発を始めた。
1993年に大学でインターネットに触り始めた身にはメールする相手がいるのは当たり前だったけど、1999年1月にリリースされたi-modeでメールアドレスを使えるようになったのに、メールするする相手がいないと聞いたのをきっかけにメル友募集サイトを作って1999年6月1日にリリースした。
それをきっかけに9月に法人化して、2001年には投資を受けたりしたのだけど、それはまた別の話。
MySQLチューニングの戦い
リリース時の環境は、友人から譲ってもらったPentium互換チップが載ったPC-AT互換機にRAM 32MB、HDDは1GBもなかった気がする。
OSはSlackwareでLinux、通信回線はOCNエコノミー 128kbpsの常時接続。
法人化前でわずかな資金の中で始めたチャレンジとしては、悪くない環境だった。
とはいえ、ApacheとMySQLを1台で動かしているので、ちょっとすると性能不足になる。
時間だけはあるので、とにかくチューニングし続けたところ、今では当たり前だったり、既に古いノウハウだったりを次々と編み出した。
クエリーはとにかく減らす
テーブル結合(JOIN)すると遅くなるので、一旦PHPの連想配列にまとめてから、別クエリーで投げる
滅多に更新しないテーブルはPHPの連想配列で定義する
Linuxカーネルは必要な機能だけに絞り込んでコンパイルしてメモリ使用量を削減する
1番目のクエリーを減らす手段の一つとしして、更新頻度が高いリストの表示でページングに関する処理がある。
ページングの有無を確認するために
SELECT COUNT(1) FROM ... /* "*"でなく1を使うのもチューニングの可能性の癖 */
と都度全体の件数を取得して確認した上で、あらためて中身を取得するクエリーを発行する(計2クエリー)のではなく、
例えば1ページあたり10件表示するなら
SELECT * FROM ... LIMIT 0, 11 /* 実際には"*"ではなく必須なカラムのみ */
と11件(N+1件)取得して、11件あったらページングが必要と判断すれば、クエリーを1つで済ませられる。
「N+1問題」との出会い
といった諸々を2000年頃から当たり前にやっていた身には、「N+1問題」というキーワードは、ごくごく最近(ここ数年?)聞くようになった語彙なので、初めて聞いた際には上記のページング処理に関するテクニックかと思ったが、実際には上記2のJOINに関連するものだった。
当たり前にやってることも名前が付くと、認知されやすくなって、改善を指摘するのも楽になる。
「N-1ロケット」との出会い…
その「N+1問題」という言い回しを、いつ誰が言い出したのか調べようと「N+1」で検索してたところ、「N-1」というよく似たタイトルのWikipediaページがあったので、早速開いてみた。
…………違う。
旧ソ連が月への有人探査をする為に1956年から1974年にかけて開発していたロケットのことだ。
試験打ち上げ4回全てが失敗して打ち切りになったものの、この時に開発されたエンジン「NK-33」は後に倉庫でホコリをかぶってるのを発見され、2013年にはアンタレスロケットに転用されて商業利用が開始されたそうな。
※ただしカバー写真は、日本の「LE-7エンジン」
ソフトウェア工学ではなく、航空宇宙工学…
ちなみに「N-1問題」というのもあるそうな。
こちらは経済学…
まとめ
そして、誰がいつ「N+1問題」と言い出したのかは、まだ調べられていない。
Wikipediaは時間泥棒…
※プロフィールとかはこちら↓