もうちょっと「艦これ」からSQLを考えてみる2
前回の続き。
「艦これ」で起きた障害は、カタログスペックの100分の1以下の処理量で発生ししていると思われる。その原因はDBサーバに対する無理解、SQLに対する無理解から起きているのでは?という考察です。
もちろん、中身は知らないけれどね。
どこで処理するか?
少し昔話から。コンピュータシステムはざっくりと、
汎用システム
クライアントサーバシステム
Webシステム
と発展してきました。
汎用システムの時代は、端末に処理能力がありませんでしたから、あらゆる処理をホストコンピュータが担っていました。これがクライアントサーバシステムになったとき、どちらで処理を行うかを考える必要が出てきました。
Webシステムになると、DBサーバ、APサーバ、クライアントのいずれもが処理能力を持ち、多くの処理をそれぞれが代替することができる。
開発時はDBサーバ・APサーバ・クライアントが1台のPCで行われることも少なくなく、クライアントサーバシステムの頃、Exeファイルを置いただけのファイルサーバのことをAPサーバと呼んでいた馬鹿者も少なくなかったので、今でも分かってない人は多いのじゃないかと想像する。
どのコンピュータで処理するかはシステム設計の根幹で、これを理解していたら、RDBMSを使う以上、「SQLを使いきるべき」と理解できるはずですが……。
前回のSQLはこういう流れになる。
赤い部分は、APサーバでも、クライアントでも代替できる処理で、そこで何をやっているかというと、
ブーストの時間内か判断(IF文)
経過秒数と増加数、前回の保有量から現在値を算出(四則演算)
最大容量を超えないか判断(IF文)
数個のIF文と四則演算を、どのコンピュータにやらせるかによってシステムダウンするかどうかが変わる。それほどシビアなチューニングがなされたシステムであれば、カタログスペックに近い性能が出ているでしょう。
赤い部分、つまりIF文と四則演算は、どこで処理してもシステムに与える負荷は誤差レベルです。
本来はこうすべき
それぞれのサーバの負荷、パフォーマンス、コーディングを考えて設計すればこうあるべきでしょう。
SELECT -- カラムの羅列(省略) , CURRENT_TIMESTAMP FROM ユーザステータス AS a INNER JOIN 増加マスタ AS b ON a.ユーザレベル = b.ユーザレベル INNER JOIN ブーストマスタ AS c ON a.ブーストレベル = c.ブーストレベル WHERE a.id = ?;
DBサーバ、APサーバのどちらで処理を行っても、データの転送量も転送回数も大差はないため、「どこでやっても同じ」なら「キレイなコーディングになる方が良い」と判断できます。
データはDBサーバにしか存在しませんから、これ以上、DBサーバの処理を減らすことはできません。つまり、JOINを避けるなどSQLを分割しても、DBサーバの処理は増えるだけで減ることはないのです。
SQLでどこまでできるか?
それはどんな流れになるか?
コーディングはどちらが分かりやすいか?
などが設計段階で見えてないと本来は設計できませんが、そういう人はほとんどいないでしょう。
もちろん、SQLが苦手な人が設計してもこうなることはありますが、それは偶然に過ぎないのです。分かってないんですから……。
SQLを除けて考えれば理解できる
データを保存しているデータ処理を、SQLではなくオブジェクト指向言語などで可能なコンピュータ(データサーバ)があったとします。
データサーバがデータを読み込むときは、メモリー上に展開する必要があります。
データサーバのメモリー上に展開したデータを、別のコンピュータに転送。
別のコンピュータでも、当然、メモリー上に展開し、データ処理(IF文、四則演算など)を行う……。
どう考えても無駄ですよね?
ですから、データサーバが扱う言語がSQLではなくオブジェクト指向言語で処理が可能だった場合、ほとんどの人が、わざわざ別のコンピュータにデータを送って処理しようとはしないはずです。メモリー上にデータを展開しながら、データ処理(IF文、四則演算など)を行って、結果だけを別のコンピュータに転送するでしょう。
しかし、「SQLは訳が分からない」「分かったつもりになっている」人達は、平気でそれをやろうとしますし、それが正しいと主張します。おかしいでしょう?
「SQLで処理したら遅い」
「SQLで処理したらDBサーバの負荷が高まる」
などは、全く意味を分かってない発言なんです。
SQLを魔法か何かと勘違いしているからでしょうが、SQLを受け取って、SQLをコンパイルして処理するDBエンジン(オプティマイザ)のほとんどは C++ で書かれたプログラムです。つまり、SQLは仕様書にあたり、プログラムとは等価です。実行時には C++ で書かれたプログラムがデータにループしながらアクセスするわけですから、本来、設計する人は
SQL → プログラム(オブジェクト指向言語)
プログラム(オブジェクト指向言語)→ SQL
のどちらも自在にできないと、どこまでをSQLで処理するのが良いのか決めることはできません。
SQLとオブジェクト指向言語が一致しない人達は、SQL(RDBMS)をブラックボックスとして考えて、何となく設計ができた気でいるだけです。もちろん、そんなやり方でも動く動かないで言えば動きます。オブジェクト指向言語で処理が可能なデータサーバがあったとして、どちらで処理をしても同じ結果が出るのは当たり前です。
ただし、分からない人が適当にやってる設計ですから、巧くいくかは運次第です。場合によっては「カタログスペックの1000分の1も出せない」という結果になってしまいます。
コンパイルが通っただけ
私に絡んで来るような人は、ヘボいとは思うけれど、それでも、業界的にはマシな部類でしょう。取りあえず、手続き型言語(オブジェクト指向言語)はそこそこに使っているはずです。
新人や後輩、部下の指導もしていることでしょう。
例えば、新人を指導していて、「コンパイル(ビルド)は通りましたが、よく分かりません」と言ってくることはあるし、そんなことは言ってこなくても「コンパイルが通っているだけで、頭を抱えるスパゲッティコード」は多数存在します。
何がしたいか分かってないからスパゲッティになるわけで、
まあ、新人のうちは、コンパイルを通すだけでも必死になるのは仕方がないことですから、それなりの指導すればよいことですが、もちろん、「コンパイルが通っただけ」ではプログラミングができたとは言わない。それを理解して、「今はコンパイルを通すだけで必死だけれど、ソースの意味が分かって書けるように頑張ります!」と努力している人は、どんなに時間が掛かっても、バカともカスとも言わない。
全力でサポートします。
じゃあ、新人を指導していて、「コンパイルが通ってるんですから、何が悪いんですか!動くんですから何が悪いんですか!」と口答えしてきたらどう答える?
そんな奴をプロとは呼べないでしょう。
……しかし、「INとEXISTSの違いが分かってない(MySQLはちょっと違うけど)」という人が、かなりの数います。そのレベルは、つまり、「コンパイルは通っているけれど意味が分かってない」状態な訳で、そのレベルのシステムを客に売ってるってことです。
そのレベルの人間(技術者じゃない)がド偉そうに掛かって来るから「カスのバカの」と言うのです。まあ、意味が分かってないから掛かってこれるんでしょうけどね……。
「分かってないことは拙い」
「早く理解しないと」
と思っている人にはそんなこと言いませんが、分かった気でいっぱしのプロみたいなことを言われてもね……。
サーバの性能が上がっているから、サーバが助けてくれるなら良いんじゃないの?と思うことも増えてきて、説得するのが面倒になって流されることも多くなってきましたが、まあ、理解できてないと「艦これ」程度のアクセスで止めてしまう。
プロならできるべきですね。
つづく