http://hyuki.com/yukiwiki/wiki.cgi?HowFriendFeedUsesMySqlToStoreSchemaLessData
- 項目が不定の雑多なデータを格納するのに、YAMLやJSONでダンプした文字列で保存することは、割と良くある手法だと思う。
- 目新しい(?)のは、カラムが不定なデータを検索可能にするために、非同期でインデックスを生成することだろう。
これと似たようなことをやるとして、MySQLじゃなくてハッシュデータベース使う前提で、簡潔に説明するとこういうことになるだろう。MySQLをハッシュデータベースとして使ってもよい。
- データはJSONでダンプして圧縮して、UUIDをキーにしてkey-value-storageに保存する。
- PrimaryKey=AUTO_INCREMENTなテーブルを作って、最近追加されたキーを管理しておく。タイムスタンプも付けておくといいだろう。
- 非同期でインデックスを作成する
- クエリはMySQLで処理して、UUIDを取得し、データをkey-value-storageから読み込む。
- インデックスは最新の状態を反映してないかも知れない。データを読み込んだ後でクライアント側で整合性を検査する。
メリット
- インデックスの追加、削除でテーブルがロックされない。任意のタイミングで行える。
- インデックスの作成を後回しにするため、DBへの書き込みが高速化する。
- 場合によっては、過去一週間分の検索が出来れば十分かも知れない。一週間分だけのインデックスを作成できる。
- etc, etc
- データ追加直後はインデックスが使えない
- 追加した直後は、UUIDでのアクセスしかできない。
- インデックスが最新ではないために、20件引いたのに19件しか返ってこない、というようなことがあり得る。
- 本来のlimitよりも多く取得する or 目的の数になるまでページングを繰り返す。
- あるいは、フロントのUIが「いい加減さを許容するように」設計されていれば、問題ないのではないか。
- 例えばAutopagerizeのようなものがあれば、何件表示されているかは問題にならない。
- ユニーク制約に関する問題
既存のシステムからの移行プラン
(自分の関わっているプロダクトで実際にこういう事をやりかけている)
雑感
- 書き込まれたデータがすぐに読み出されるとは限らない。インデックスの更新は非同期で良い。
- クローラを作るとそう言うことが良くある。
- データベースを更新するのはユーザーではなく、バックグラウンドで動くクローラープロセス
- だから、データの更新がすぐに反映されなくても良い。インデックスが更新されたタイミングで、初めてユーザーに反映されれば良い。
- ユーザーからのリクエストによるデータの更新は、多くの場合で、すぐに反映される必要がある。
- 通常通り、インデックスの作成を同期的に行う必要があるだろう。
- UI上の工夫で何とかなりそうなことも多いと思う。書き込みが成功したかどうかなんて、その場で分からなくても良い。
- 正確さのために無駄なロックが発生したり、インデックスを肥大化させて、速度を犠牲にしてしまう。(よくあるパターンだと思う)
- 細かいことを気にしなければコンピューターの性能はもっと引き出せるはず。