ISUCON12の問題に挑戦している

曽根壮大氏:ということで、ここまでで15分。半分ぐらいです。最後15分ぐらいはせっかくなので、自分らしい話をしようかなと思っています。

本選問題を今作っている人がいるんだったらアピールしていこうと思っているんですが、今、ISUCONで流行りのMySQLからポスグレ(PostgreSQL)に移行するということを僕は過去問から全部、毎月やっています。

(スライドを示して)今日話すのはISUCON12の予選、2022年の問題……。2022年の問題の説明をすると、MySQLというデータベースとSQLiteというデータベースが、両方問題の中にあったんですよ。それまでのISUCONの問題はだいたいMySQL1本で来ることが多かったのですが、2本出しになっていて。これをポスグレに移行することをやっています。

まずは記事の内容です。(画面を示して)これは「はてなブログ」ですが、実際のリポジトリがあって、実装を素振りでリベンジしたというものです。

一応予選スコアは超えました。なのでポスグレでも勝てるということを2023年は証明していきたいんですが、でも3時間ぐらいかかったので(笑)。練習が必要だなとは思いました。

ポスグレだったらなにがいいのか……。あっ、先に聞いておくんだった。MySQL派の人。(会場を見て)はぁ、なるほどね。ポスグレ派の人。(会場を見て)はぁ。じゃあ、「OracleDB」派の人(笑)。

OracleDBはお金がかかるので難しいと思います。ポスグレ派が少数らしいので、「ポスグレでもできるんだぞ」ということを言っていこうと思います。

ポスグレ(PostgreSQL)のメリット

ポスグレにはメリットがあって、SQLite FDWというものがあります。これがなにかというと、ポスグレからSQLiteに直接つなげられるんですよね。FDWとかで調べたらすぐ出てきます。

そうするとなにがうれしいかというと、SQLiteのデータをポスグレに取り込みたいわけです。でも、取り込むためにはSQLでSELECTしてとか、INSERTしてとか、そういうツールを書くのは大変です。でも、SQLite FDWならなんと全部やってくれます。

ISUCON12の予選問題への他グループの対応から学んだこと

MySQLやMongoDBなど、メジャーなデータベースのFDWがだいたいあるんですよ。その中でもSQLiteはわりとメジャーで、上から順にやっていくと作れます。

1個だけ問題があって、ISUCON12の問題です。これはわざとだと思うのですが、SQLiteのデータ(ベースファイル)がデフォルト(初期実装)で100件あるんですよ。増えていくんです。だから全部をコピペしていくのは難しいということで、PHPでシュッとSQLを自動生成して、自動生成したSQLで実行して移しています。

ISUCONにGoで出たらGoで解かないといけないと思っているじゃないですか。fujiwara組はGoで出ているんですけれども、データ、画像をDBから取り出して、ファイルにする時などは、Perlをシュッと書いていました。

「あっ、そういうやり方もあるんだ」と思って。それなら、本選を解く時のメイン問題はGoで書いてみるけれど、Goは文字列生成がGoは苦手なので、「得意そうな言語でやってみよう」とか「自分がすぐ書けるやつでやってみよう」と。

こういうのも過去問などを読んでいると、「あっ、なるほど、そういうアプローチがあるのか」ということで、自分で試してみた例です。これで100件分のSQLが自動的にダンッて生成されて、それを流し込むだけで移行が完了するというスクリプトの話です。

スキーマを移行におけるChatGPTの活用例

ほかにもいろいろあります。(画面を示して)プライベートリポジトリなので(イベントに)来た人だけに見せていくかという話ですが。これは僕じゃなくて瀧澤のリポジトリなんですよね。

どういうところで苦労しているかというと、「ポスグレに移行するんじゃ!」と、余裕があるうちはかっこいいタイトルをちゃんとつけています。これはちゃんと8時間という制約を入れてやっているんですが、時間が経つたびにコメントがだんだん短くなって、「チューニング」となっていくんですね。

これはISUCON12の予選なので2022年の問題です。

MySQLからポスグレに移すことをやっていて。一番大変なのは、やはりDDLとSQLの互換性がないところなんですよね。

MySQLのフォルダーをいきなりSQLをバンと書き換えて、「上書きじゃ!」ってやるとだいたい事故るので、事故らないように、まずpg(postgresql)、ポスグレというフォルダーを作って持っていきます。

(画面を示して)スキーマを粛々と移しているのですが、スキーマを移すコツは1つあります。ChatGPTっていう人がいて(笑)。

本選の問題は、MySQLのテーブルの数が多いんですよ。3つぐらいだったら手動でやってやってもいいかと思うんですが、20個ぐらいテーブルがあって、「面倒くせぇな」ってなります。

なので、1個をとりあえず移して、「こういうふうにMySQLのテーブルをポスグレに移し替えたんだけど、ほかのテーブルもやってください」と貼りつけると、やってくれる。だいたい良い感じになります。ChatGPTの活用例でした。

ISUCONは最初にデータをリセットしなきゃいけない

(画面を示して)このあたりのINSERTも先ほどPHPで自動生成したやつとかをベタッと貼っている感じです。

テーブルを作って、sqliteというスキーマを作っておいて、そこにSQLiteをマウントします。そこからマウントしたやつをSELECT INSERTでデータを持ってくることによって、イニシャライズの処理をします。

ISUCONは最初にデータをリセットしなきゃいけないんですよ。データをリセットする処理がこの問題の難しいところで、とても大きいデータだからリセットを30秒以内にできなくて。みんなが初期化に失敗して落ちるみたいなのが罠なんですが、そういうのも簡単なたったの15行ぐらいのことで解決します。

(画面を示して)細かいところがあってデータを移していった感じなんですが、このあたりのことはそんな大したことじゃなくて。

実際に難しいところでいうと……。どれがいいかな? テナントをポスグレに移すみたいなものです。

既存のコードをいきなり上書きしないことが大事

小さくやっていくことが大事で。まずは既存のコードをいきなり上書きしないことです。これは僕らの素振りでの反省です。いきなり同じ関数名の名前を作って直すと、どこから壊れたかわからなくなるので、もともとのコードはコメントアウトして下に書くか、別の関数名の名前を作ってそっちの名前を呼ぶようにします。

これもめちゃくちゃ大事で。そうすることによってロールバックしやすくするとか、とりあえず呼んでいる関数を元に戻すだけで直るから、元が悪いのかどうかわかるみたいな感じです。なんでもいきなりBreaking Change(破壊的変更)に入れないのが大事ですね。

(画面を示して)こことかも、コメントアウトして必要なところだけやっていくということをやっています。

(画面を示して)このコードはトランザクションを入れるとか外すという処理なのですが。

まずはミニマムなところからやっていって、最終的に5段階とか6段階ぐらい進んでから全部入れるのは大事かなと思っています。まこぴー(谷脇真琴氏)とかはそれがうまいんですよね。

素振りではベンチマークスレッドを使っている

あと、僕らはalp使っているんですが、実際にそれが効果があったかどうかは、ちゃんとベンチマークスレッドを作って……。

(画面を示して)これは素振りなので本選や予選に出た時はありがたいダッシュボードがついてくるのですが、自分たちで素振りする時はダッシュボードがついてこないので、ダッシュボードの代わりにやっていきます。

ベンチマークを実行して初期スコアが4,000点ぐらいなんですが、実際にこういう改善をしたら……。例えば「#13をマージしたらこういうことになりました」みたいなことを続けていくと、「これ、効果あったね」「なかったね」とかがわかる。

alpというツールがあって。これはアクセスログをいい感じにしてくれるやつで、「ボトルネックがここだから、まずはplayerをやっていくか」とか、「ボトルネックが変わってきたね」みたいなことを判断しながらやっていきます。

(画面を示して)例えば、ここらへんはスコアが上がらなくて苦しんでいますね。スコアが8,000点ぐらいしかなくて、下がったと。

(画面を示して)これはめちゃくちゃ上がった感じです。

変更をしたけれどスコアが下がったということは、間違っているじゃないですか。そうしたら元に戻すかとか、revertするかとか、そういうかたちで小さくスコアを確認しながら上げていきます。

だんだんスコアが上がってきて、「おっ、そろそろ僕らも優勝できるぞ」みたいなところから、「10万点超えたぞ」と言っています。でもね、マージした時間がすでに17時とかなんじゃないかな。

「10万点超えたね」。ワイワイとやっていって、最終的なスコアが11万5,000点ぐらいなので、一応予選は突破したということがわかります。

僕らは過去問でこういうことをだいたいやっていて。そうするとMySQLとポスグレの違いも両方学べる。

例えばISUCON10だと「ISUUMO」という、空間インデックスを張るものが問題の趣旨としてあるのですが、「それをポスグレでやったらどうなるの?」って。対応方法としてはPostGISになるんですけど。

僕はPostGISを使ったことがあるけど、チームメンバーは使ったことがないから、実際にライブラリをインストールして、インデックスを張ってみるとか。実務には近いんだけれど経験したことがないことを学べるのも非常にいいところかなと思っています。

こういう感じでみんなでワイワイ素振りをやっていくのも大事かなと思っています。僕らは来週も素振りをやります。瀧澤君がすばらしいツールを用意してくるんじゃないかなと思っています。

「できる」という決断は自信がないとできない

僕はISUCONは失敗するんですけど登壇は失敗しないので、ちゃんと時間どおりにやっていこうと思います。おまけが終わったので、まとめの話をしていこうかなと思います。

(スライドを示して)これは僕の2020年ぐらいの時の反省です。当時は僕がリーダーをやっていて、yokuさんとkamipoさんというMySQLのスペシャリスト3人で出ようと言って出たのですが、やはりふだんやっていないことはできないとすごく感じました。僕は一応MySQLもそれなりに知っているつもりなんですよ。でも、知っているのとできるのはぜんぜん違うなと思っています。

知識として、例えば仮想列や空間インデックス、レプリケーションとか関数インデックスとかがある。あるのを知っていると、「ここで使ったらうまくいくよね」と言える。

「そもそもレプリケーションはどうやって張るんだっけ」とか。調べながらやれば、レプリケーションもみんなはたぶんできるんですよ。だけど、それを8時間のうちにやらないといけないという時に、「できるんだっけ?」と決断できるかどうかは自信がないとできないんですよね。

知っていてもできなかったことがたくさんあるなという反省から、できるようになるには、やはり積み重ねしかないなということで、1年間素振りをやっています。

スライドの下にも書いているんですが、技術力という表現。ここでは筋力と言っていますが、できるようになるのは、やはりやったことがあることしかなくて、やったことがあることを日々積み重ねていって、筋力が強くなっていきます。

ISUCONだとマルチスレッドでやるとか、デバッグ力とか、いろいろな能力が試されるのですが、そういうのもいきなり全部は強くならないので、1個1個強くしていくしかないなということを反省した1日で、ISUCONを通して僕を育ててくれているなと思っています。

ISUCONの時の反省ですが、ISUCONの攻略法ってなんだろうと考えたら、結局、エラーログ、コード、設定をちゃんと読むということを1個1個積み上げていくのがどれだけ早いか。一番の正攻法です。

最新のテクニック、モダンななんとかとか、Privateメソッドにテストを書くかどうかとか、そういう話も大事なのですが、やはりこういうことを毎日ちゃんとやっていかなきゃいけなくて。こういうことをやるのに、ISUCONは非常によくできた修行の場なんじゃないかなと思っています。

やはりISUCONの借りはISUCONじゃないと返せないので、予選落ちした以上、2023年は優勝を目指してがんばっていこうと思っています。(スライドを示して)これは2021年のツイートですが、毎年同じことを言っています(笑)。

ということでみなさん。ぜひISUCONで会いましょう。ご清聴ありがとうございました。