ディスカッション (11件)
最近、何でもかんでもデータベースに頼りすぎていませんか?実は、プロジェクトの規模や用途によっては、複雑なデータベースを導入するよりも、シンプルなファイルベースの管理や静的ストレージを活用する方が圧倒的に効率的なケースも多いです。パフォーマンスを最適化し、技術的負債を減らすための「データベース不要論」について議論しましょう。
大昔にPerlで小さな販売管理ウェブアプリを作ったことがある。ISPのサーバーに何もインストールできなかったから、ファイルベースのハッシュ(ユーザー用、注文用、その他用と分けて)を使っていたよ。
時が経つにつれて、クライアントがもっと良いシステムに移行するだろうと思っていたけど、彼は亡くなるまでの約20年間ずっと使い続けてくれた。家族が引き継いでからは全て作り直したみたいだけどね(今はWordpressで動いている)。
最後に確認した時、注文データは数十万件もあったのにパフォーマンスは良好だった。ハードウェアの進化のおかげで、このやっつけ仕事みたいなシステムが予想を遥かに超えて長生きしてくれたんだ。今の時代なら、SQLiteで全く問題ないはずだよ。
関係データベースは恐竜じゃなくて、サメなんだよね。
https://www.simplethread.com/relational-databases-arent-dinosaurs-theyre-sharks/
小さなアプリで得られるごくわずかなメリットのために、車輪の再発明をする時間を費やすのは割に合わないよ。
独自のストレージを書いてみるのは、データベースの仕組み(インデックスや適切なデータ構造などを効率的に維持する方法など)を理解するには最高の方法だね。でも、ただの実験じゃなくて本気で開発するつもりなら、最初から既存のデータベースを使うべきだったという結論に至るはず。
コンピュータがいかに高速かを証明していて、すごく好きな記事だ。ただ一点、同意できない結論がある。記事の後半で筆者はフラットファイルでは力不足になるケースを挙げた後、「これらの制約の多くは、多くのアプリケーションには当てはまらない」と言っている。
でも制約の一つに「複数のプロセスが同時に書き込む必要がある」というものがあるよね。初期段階のプロダクトでも、cronや別ワーカーで動くメッセージキューが必要になることは多い。こういった複数のプロセスは、同時に書き込みが必要になることがよくあるんだ。メインサーバーだけが書き込むように工夫することもできるけど、そうするとアーキテクチャが複雑になりすぎる。
純粋なスケールの観点では筆者に同意するけど、広い視野で考えれば、データベースを使うのが一番だね。SQLiteならとても賢い選択肢になる。もしスケールが必要なら、よくアクセスされるデータをインメモリでキャッシュすれば、両方のいいとこ取りができるよ。
僕の鉄板の組み合わせは、SQLiteとインメモリキャッシュだね。
アトミック性が必要なら、データベースは必須だよ。ファイルシステムの上だけでアトミックな書き込みを実現するのは極めて不安定だ。
データベースの多くが永続化の問題を抱えていて、クラッシュ時にディスク上のデータが簡単に壊れてしまうのもこのせいだね。WindowsでのRocksdbが良い例で、数年前、開発中に頻繁に破損問題が発生していた時期があったよ。
どうだろうね。組み込みシステムでさえ、データベースなしで始めた時は、結局最後にはデータベースのようなものが必要になってきたんだ。どの場合も、マーシャリング/アンマーシャリング、ファイル管理、通知などをアプリ内にアドホックで管理しきれないデータベースを構築する羽目になった。普通のファイルの上に機能を追加していく方が、データベースシステムに切り替えるより手軽だったからなんだけどね。
ただ、データベースを導入する動機は、単にデータを管理することではなく、関係型や非関係型のデータを不揮発性メモリ上で扱うための優れた抽象化レイヤーを得られることにある。他のシステムが書き込んでいる最中でもアクセス制御ができるしね。良い抽象化があれば、自分の好きな言語で既存のライブラリを活用できるから、ファイルシステムの上に全てを自作する必要がない。これは、新しい機能を追加したり、既存システムとの相互作用を増やしたりする際に、連鎖的な効果を生むんだ。
複数のプロセスが同じデータで通信する必要がある場合も、データベースなら理にかなった抽象化と同期の仕組みを提供してくれる。普通のファイルやIPCを使うと、そういった仕組みを自分たちで発明しないといけなくなるからね。メッセージングで更新を通知することもできるけど、それだと全てのデータが2つずつ存在することになり、どちらのコピーも矛盾しないように更新をアトミックにする必要がある。それなら最初からデータベースを使った方がいいと思わない?
今となっては、トランザクション用じゃなくても、何らかのデータベース抽象化から始める。データ共有、整合性、アトミック性、通知といった多くの懸念事項を最初から解決しておく。そうしないと、信頼性の問題で結局後から全部作り直すことになるからね。
面白い試みだけど、本番環境でSQLiteや他のDocker化した関係データベースの代わりにファイルを選ぶのはちょっと躊躇するな。
アプリケーション開発の最も簡単な部分、つまり「始まり」に対して過剰に最適化しすぎている気がする。結局、安全な機能が何もない「データベースのようなもの」を中途半端に実装しているにすぎない。この記事が触れていない、将来的に直面するであろう多くの頭痛の種があるよ(経験したことがないだけかもしれないけど)。
参照:https://danluu.com/file-consistency/
例えば、ユーザーとプロファイルを紐付けたり、ユーザーと組織を紐付けたりと、機能の範囲を広げる必要が出てきたらどうするつもり?
考えてみてほしい。ファイルベースで構築したアプリを、長期にわたって運用し続けているショップがどれだけあるだろうか?おそらくほとんどいないはずだ。つまり、これは結局あとで二度手間になる可能性が高い。
人々が最初からデータベースを選ぶのには理由がある。こういうやり方は避けた方がいいと強く言いたいね。
記事は悪くないけど、一点だけ指摘させてほしい。
「あなたが使ったことのある全てのデータベースは、コードがopen()を呼ぶのと全く同じようにファイルシステムを読み書きしている」
技術的には正しくないよ。SQLiteのようなアプリケーションはmmapを使って、ファイルをローカルのアドレス可能なメモリ空間にマップしている。これによって、読み書きの際にシステムコールをスキップできるんだ。カーネルはユーザーランドのプロセスよりもずっと速くデータを動的にマップできるからね。
記事の後半でファイル全体をメモリに読み込む処理について触れているけど、ここでもmmapの方がずっと優秀だ。そのアプローチが使われていたらもっと良かったんだけどね。
めちゃくちゃ共感する。システムの設計面接をよくやるんだけど、フラットファイルで十分、SQLiteで十分という問題を出すと、その事実に気づく候補者はめったにいない。ほとんどは、全く不要なマイクロサービスやキュー、巨大な分散データベースを山のように提案してくるんだ。
SQLiteは大好きだし、考え方も素晴らしいし、成熟していて軽量なものがあるのは最高だ。だけど筆者と同じく、特定のケースではオーバーキル、あるいは力不足だと気づいたよ。
検索機能付きのクライアントサイド辞書アプリを作っていた時、SQLiteのWASMポートが完璧なソリューションだと思ったんだ。
数年間SQLiteを使ってみたけど、段々と負担になってきた。データベースファイルが必要以上に大きくなるし、圧縮もあまりうまくいかない。ロード時間も少し遅い。線形検索もあまり速くないし、SQLiteファイルの編集や結合などの処理も遅くてイライラした。もっとシンプルなものが欲しかったんだ。
アトミック性も書き込みも必要なかったので、ソースのtsvファイルから自分でインデックスを自作してzstdで圧縮し、ロード時にWASMで解凍するようにした。すると、SQLiteでそのまま読み込むより解凍してロードする方が速くなったんだ。モジュールもSQLiteの800kbに対してWASMで52kbに収まったから、いくらでも好きなだけロードしても問題ない。線形スキャンにはstringzillaを使っていて、とんでもなく速いよ。
SQLiteは素晴らしいツールだけど、どんな問題にも万能な解決策というわけではないね。