ほぼ静的な個人Webサイトに最適なデータベースとは。
はじめに
当サイトでは、データベースにMongoDBのクラウドサービス(Atlas)を利用していました。しかし、1年半ほど利用したところ、だんだんと使用容量が増えてきました。
無料枠では512MB使えるのですが、既に338MB使われています。私の場合、コンテンツ量はかなり少ないのですが、oplogという変更ログが多くの容量消費しています。
localというデータベースにoplogが入っています。1.4GBの全てがクラウド使用の容量としてカウントされている訳ではなさそうですが、他のDBは全て足しても180MB程度なので、oplogだけで150MBくらい消費している計算になるかと思います(oplogの実際のサイズは権限の問題が取得できませんでした)。
このoplogですが、結構なスピードで増えてきているのと、権限の問題で削除や容量の削減が難しそうだったので、早いうちに他のDB製品に移行することにしました。
最終的にSQLite3に移行したのですが、どういう理由でこれを選んだのか、共有したいと思います。個人製作のほぼ静的なWebサイトだと、データベースはそこまで大掛かりなものは不要なことが多いはずなので、参考になれば幸いです。
Webサイトでのデータベース選定
一言でWebサイトといっても、データベースへのアクセス多寡は、Twitter(X)のような巨大SNSや、ブラウザ・ゲーム、個人制作のWebサイトでは全く異なります。
読み書きの頻度や、リアルタイム性、アクセス数、データ量等、様々な要因によって、最適なデータベース製品は変わってくると思います。そのため、「WebサイトならこのDBで決まり」と単純に決まることはありません。
なので、まずは当サイトでのDBの利用状況について共有します。あくまで、私のような用途であることを前提に記載していますのでご了承ください。
当サイトの場合
このサイトは、9割5分以上静的なコンテンツです。ブログが実質メイン・コンテンツなので、リアルタイム性が求められるページはほとんどありません。リクエスト時に、オン・デマンドでDBにアクセスするページは、boardページだけです。(そして、このページはほとんどアクセスはありません。)
後は、ブログページの下にある「いいね」ボタンとか、コンテンツのアップロードに使う管理画面でDBにアクセスする処理はあります。しかし、いずれも限定的な用途なため、読み書きの回数も少ないですし、データ量も大したことありません。
本番環境でデータベースが使われるのは、このくらいです。文字化してみると、あまり使っていないなと改めて感じます。
他には、サイト内のURLに応じた画像等のコンテンツの置き場所や、HTMLのheadタグ等で使用するメタ情報をデータベースに格納しています。開発環境で「ビルド」する時、これらを取得してページの生成を行っています。後は、サイド・バー(モバイルの場合はページ下部)の「関連記事」を生成するためのキーワードも、データベースに入れています。これもビルド時に使います。
上記のとおり、私の場合は本番環境よりビルド時のほうが活躍の場面が多いです。本番環境においては、「ほぼ静的なサイト」と言えると思います。
移行前のDB:MongoDB(Atlas)
移行前のデータベースには、MongoDB Atlasを利用していました。
MongoDB Atlasとは
MongoDBとは、いわゆるNoSQL型のデータベースの代表格です。異なるフォーマットのデータを格納することもでき、関係データベースより柔軟な使い方が可能です。
MongoDB Atlasは、MongoDBのクラウド・サービスです。約512MBまで無料で使うことができます。
当初、クラウド版じゃないローカル版のMongoDBを入れようとしていたのですが、うまいことAtlasに誘導されてしまったのは内緒です。
私が感じたメリット
セット・アップが楽
通常、ローカル版のMongoDB、Postgres、MySQといったデータベースは、サーバーとして稼働させるかと思います。Webサーバーとは別に起動させる必要があり、アプリと接続させるために、ユーザや認証情報の設定、稼働させるポートの指定等、様々なセット・アップが必要になります。また、DBサーバーとWebサーバー2つある分、デプロイの作業やリリース後の運用も煩雑になりがちかと思います。
Atlasはクラウド・サービスなので、DBサーバーを自前で構築する必要がありません。基本的にはWebサーバーのことだけ考えていればよく、環境設定やリリース作業のような運用はかなり楽だと感じました。本番環境ではリバース・プロキシ・サーバーのようなサーバーも絡んでくることが多いとは思いますが、いずれにしても自前で管理するものが減りますので、メリットと言えると思います。
JSONと相性が良い
これは完全にアプリ内の話です。MongoDBに投入できるデータはJSON形式と互換性が高く、JavaScriptのようにJSONへのパースが容易な言語と親和性が高いです。そのため、プログラムでDBの読み書きを行う処理は、案外シンプルに実装することができました。
MongoDBの公式CLI(MongoDB Shell)も、Node.jsで実装されています。もちろん覚えることはありますが、コマンド・ラインからの操作も比較的簡単に行うことができるかと思います。
とはいえ、関係データベースでもPrismaのようなORMも登場しており、MongoDBと同じようにJSON形式と親和性が高くなっているのかもしれません。使ったことがないのでコメントできませんが、、、。
開発環境と本番で同じDBを参照できる
これは一長一短かもしれません。
クラウド・サービスなので、本番でも開発環境でも同じDBを参照することができます。ちょっとデータの更新をしてテストをする際は、本番にも影響が出る場合もあるので不便な面もあります。しかし、本番と開発環境のデータの同期を行う必要がないので、私の使い方ではメリットの大きかったです。
MongoDBのローカル版でも、同じことはできるかもしれませんが、設定等は結構面倒になるかと思います。
その他
私の場合だとメリットを享受てきていませんが、、、一般的に、RDBと比べMongoDBは水平スケールがしやすいと言われています。なるべく各ユーザの近いところにDBを置き、レイテンシを減らすような戦略が取りやすいようです。私からしてみると気の遠くなる話ですが、世界中からアクセスがあるようなサイトだと、便利そうですね!とはいえ、Webサーバーとかも同じようにスケールさせる必要はあるかと思うので、データベースだけでは全体のパフォーマンスは変わらないでしょうけど。
デメリット
MongoDB自体のデメリットというより、単純に私の用途とミスマッチだっただけ、というものも含まれています。
oplog.rsの容量が増えていく
これははじめに記載したとおりです。実データはさほど増えていないのに、oplogの容量がどんどん増えていきます。しかも、Atlasだと容量の上限設定等、oplogに関する捜査権限がデフォルトでは与えられていません。一応マニュアルに沿ってoplogの容量上限を設定しようとしましたが、うまくいかず、最後まで解決できませんでした。
まぁ私のせいかもしれませんが、、、全体的にマニュアルが分かりにくく、意図的に分かりにくくしているのか?と邪推してしまいます。
もし、Atlas無料枠でoplogの容量を削減したり上限設定する方法を知っている方いたら教えてください。
使わない機能が多い、、、
MongoDBにはレプリケーションと呼ばれる機能がついています。同じデータを複数のデータベースにもたせ、冗長化する機能です。冗長化だけでなく、いわゆるシャーディングとか、クラスタリングとか、ロード・バランシングにも役立つようです。こういった機能が、「水平スケールに強い」と言われる所以なのでしょうかね。
サーバも、現にPrimaryサーバとかSecondaryサーバ(2台)に分かれています。
とはいえ、このあたりを手動で設定しないと使えない訳ではありません。特段何も意識せずとも普通に使えます。私も意識することはなかったですし、特段実害はありませんでした。しかし、明らかにもっと大規模な用途を想定したサービスになっているため、「場違いなものを使っている」気分はありました。「Webサーバーは1箇所に固定されているのに、データベースだけ水平スケールする意味ある??」と感じてしまいます。
ドキュメントが分かりずらい
私が悪いだけかもしれませんが、全体的に公式のドキュメントが分かりにくいです。内容が分かりにくいというより、必要な情報が探しにくいです。日本語のページもありません。後、全体的にAtlasに誘導しているような印象を受けます。
大きな製品なので、公式以外にも情報は充実しているのであまり困らないかもしれませんが。
移行後のDB:SQLite3について
移行後のDBは、SQLite3です。何故SQLite3にしたかは、メリットの部分で触れます。
SQLite3とは
いわゆる関係データベースです。しかしOracleやMySQL、Postgreといった他の関係データベースと、大きく異なる点がいくつかあります。
データベースが「ファイル」
SQLite3のデータベースは1つの「ファイル」として管理されます。他の関係データベースは、MongoDBと同じく「サーバー」として稼働させますが、SQLite3だとただのファイルです。ユーザや認証情報を設定することなく使うことが可能です。
組込みやIoTでよく使われる
通常、データベースは複数の端末からアクセスされることを想定して設計されています。Webのバックエンドのように、複数の端末から送られてくるデータを集中的に管理するために使われることが多いです。一方、SQLite3はスマートフォンのようなモバイル機器や、IoT等のデバイスに組み込まれることが多いようです。公式サイトによると、「全てのスマートフォンで使われている」と記載されているので、AndroidでもiPhoneでも使われているようですね。
じゃあWebサイトに向かないのかというと、そういう訳ではありません。公式サイトでも「低~中程度のトラフィックのWebサイトなら向いている」と記載がされています。「(DBをどのくらい使うかにも依るが)1日10万程度のアクセスなら問題ない」(!?)とも記載されています。
どういう用途に向いているかは、公式のAppropriate Uses For SQLiteに詳しく記載されています。興味のある方は見てみてください。SQLite3にするか、他のclient/server方式のデータベースにすべきかの基準も記載されているので、とても参考になります。
私が感じたメリット
簡単にアプリに組み込める/初期設定不要
データベースがファイルなので、サーバーとして起動させる必要がありません。そのためアプリへの組み込みが簡単です。煩雑な初期設定もなく、運用も手間がかかりません。バックアップもファイルをコピーするだけなので、簡単に実装できます。
Webサーバと同じ筐体にある
Webサーバーとデータベースが同じマシン上にあるので、レイテンシはほぼゼロです。MongoDB Atlasのようなクラウドサービスだと、よくて「Tokyoサーバー」だと思うので、NWの伝送時間という観点では、圧倒的に有利です。もっとも、時間の差を体感できるほどではありませんが。ただ、ネットワークの速度は外部の要因で遅くなることもあるので、外部リスクを1つ減らしたと評価することもできるでしょう。
これで十分だと感じる、、、!
SQLite3は、上述のとおり主に組込み機器で使われます。他製品と比べると、「簡易的なデータベース」という印象を持っていました。これはある意味事実です。しかし、実際にWebサイトで使ってみると、「簡易的なデータベース」で十分ではありませんか。いまのところ、データベースとしての役割を果たしてくれています。
「(自分にとって)不要な機能が少ない」というのは、管理面でも楽ですし、気持ち的にも不思議と楽です。
デメリット
公式が「こういう用途には向いていない」と言っているものや、一般的に言われているものです。私が実際に感じたのは1点目と2点目です。
JavaScriptとの親和性はMongoDBに劣る
関係データベースなので、データの操作はSQLで行うことになります。そのため、JSON形式と互換性の高いMongoDBと比べると、プログラムからデータベース操作を行うのに手数が増えます。
例えば、複数のカラムをもったテーブルに対し、何れかのカラムを更新するような処理を書く場合、案外面倒臭かったりします。UPDATE SOME_TABLE SET ~~
の「~~(カラムの部分)」が可変になるため、動的に設定する必要があります。複数のカラムの組み合わせで更新を行う場合、もっと面倒臭くなります。
もっとも、私の技術不足もあるでしょう。PrismaのようなORMを使えばこの点は解消するのかもしれません。
本番と開発環境でデータベースが分かれる
これは一長一短かと思います。
MongoDB Atlasの時は、本番も開発環境も同じデータベースを利用していましが、SQLite3に移行して分かれてしまいました。開発機から本番機のファイルを直接見に行くことは難しいですし、下にも出てくるように、複数ユーザで同じファイルを操作するには向いていないため、分ける必要があったのです。
分けたことにより、デプロイが「本番データベースの更新」「開発機にコピー」「開発機でDocker Image作成」「本番にImage転送して起動」というまわりくどい手順になってしまいました。もっとも、これはサーバーのスペックの都合で開発機でDockerのImage作成を行う必要があり、この制約の下での作業だからです。スペックの問題をクリアすれば、もっと単純になる予定です。
ロックが厳しい
レコード単位のロックや、テーブル単位のロックはできません。データベースごとロックされます。書き込み時はデータベースごとロックされ、デフォルトの設定ではその間は読み取りも行うことができません。WALを有効にすることで、「読み取り中の書き込み」や「書き込み中の読み取り」は出来るようになります。WALは私も試せていないので、詳細は割愛します。
このため、特に書き込みが高頻度で行われるような場合、SQLite3は向かない場合があります。
複数ユーザの同時利用には向いていない
これはデータベースが「ファイル」であるためしょうがないのかもしれません。
もっとも、Webサイトで使う場合は、ユーザは基本「Webサーバー」だけなので、通常問題にならないと思います。本番稼働中にデータベースのメンテナンスをする場合に、もしかすると不都合があるかもしれません。私も運用する中で何かトラブルがあれば追記します。
ユーザの設定ができない
データベース・ファイルが開ければ、読み込みも書き込みも出来ます。「データベースのユーザ」という概念がそもそもなく、権限をユーザごとに付けるということもできません。やるとすれば、データベース・ファイルのパーミッションを適切に設定するくらいでしょうか。
複数人で同時で使うことをあまり想定してしない製品ということもあり、ある意味当然です。そのためデメリットとは言えないと思いますが、用途によってはユーザごとの権限設定が必須というケースもあるでしょうから、ここに記載しました。
暗号化ができない
デフォルトではデータベースの暗号化の機能はなく、拡張機能を使う必要があります。
私の結論
SQLite3あまりWebサイト用途には向かないのかな、と先入観をもっていましたが、用途次第では十分ですね。
私の使い方だと、本番環境でのデータベースの書き込み頻度はかなり低いです。MongoDBやPostgreのような、大型アプリケーションでも使われる製品だと、使わない機能も多く、正直手に余ります。SQLite3でちょうど良く感じます。初期設定不要で手軽に使えるのも良いですね。
ほとんどの個人製作のサイトは、静的なコンテンツがメインかと思います。データベースへの書き込みも、そこまで多くないのではないでしょうか。もしかすると、MongoDBやPostgresのような製品だとオーバーキルで、SQLite3で十分な場合も多いと思います。
もし、ほぼ静的なサイトのデータベース製品に悩みがあったら、ぜひSQLite3も検討してみてください。
参考
- MongoDB Atlas: https://www.mongodb.com/ja-jp/atlas
- SQLite3: https://www.sqlite.org/