Googleのエンジニアが次の構造のMySQLデータベースを使用するとします。
文書
--id
-名前
--creator_id
シーツ
--id
--document_id
-名前
行
-数
--sheet_id
-高さ
列
-数
--sheet_id
-幅
細胞
--id
--sheet_id
-色
-コンテンツ
--row_number
--col_number
--creator_id
前述したように、誰でもドキュメントにアクセスできます。たとえば、セルの値をわいせつな単語に変更すると、以前の値が完全に破棄されます。
構造要件
必須
- 以前のセル値を保存する機能
- オンラインドキュメントの以前のリビジョンを表示する機能
- 前のバージョンにロールバックする機能
- 一部のパラメーターには異なるバージョン(id、sheet_id)がない場合があります
- 使用されるORMでの実装
望ましい
- データを新しい構造に転送し、データをサンプリング、変更、追加するための最小限の人件費
- ディスク容量を節約する
- 古いリビジョンを表示するときに変更されたセルを強調表示する
実装
多くの審議の後、「公式」が導き出されました。 追加のテーブルを作成し、メインテーブルと、異なるバージョンの値を含む新しく作成されたテーブルを結合するとどうなりますか。
まず最初に、リビジョンを含むテーブルが必要です。
改訂
--id
--parent_id
--document_id
--created_date
バージョン管理を必要としない情報がセルとcells_data-ユーザー変更情報に残るように、セルテーブルを2ずつ分散します。 さらに、cells_dataテーブルにcreated_in_revision_id、deleted_in_revision_idフィールド、および変更を行ったユーザーの識別子を追加します。
細胞
--id
--sheet_id
--row_number
--col_number
--creator_id
cells_data
--cell_id
-色
-コンテンツ
--data_creator_id
--created_in_revision_id
--deleted_in_revision_id
(cell_idの主キー+ created_in_revision_id)
Documentオブジェクトのコード(客観的にプログラムする場合)にgetRevisionConditionメソッドを追加します($ revisionId = false)。これは、「created_in_revision_id in(0,100,300,301)and deleted_in_revision_id not in(0,100,300,301)」のようなSQLプレフィックスを返す必要があります。 つまり 現在のリビジョンとそのすべてのパートナーを、「in(...)」および「not in(...)」に含む
サンプリング
次はquarです。以前は次のように見えていました。
select * from cells where row_number=3 and col_number=2
になります:
select c.*,cd.* from cells c,cells_data cd where row_number=3 and col_number=2 and id=cell_id and $revisionCondition
もちろん、これらのテーブルのフィールド名は複製しないでください。
新しいレコードを挿入
ここでのすべては、サンプリング時と同じくらい簡単です。 リビジョンの有効期限が切れているかどうかを確認し、最後のものを取得します。 たとえば、次のように:
$revision=$document->updateRevisionIfExpired()
まず、メインテーブル(セル)に挿入してから、バージョン対応データを含むテーブル(cells_data)に挿入します。 created_in_revision_idフィールドに、最新のリビジョンのIDを書きます。
レコードを削除
ここでは、ディスク容量を節約しようとします。 たとえば、リビジョンの有効期間として30分を設定した場合、削除されたレコードのリビジョンを現在のリビジョンと比較し、次のようにします。
- それらが一致する場合-データベースから削除するだけです
- リビジョンがすでに変更されている場合は、単純にcells_dataテーブルのフィールドに新しいリビジョンのIDを書き込む-deleted_in_revision_id
node.jsの場合、これは次のようになります。
if(cellRevisionId==currentRevision.getId()){ db.online.query("delete from cells_data where cell_id="+cellId+" and created_in_revision_id="+cellRevisionId) }else{ db.online.update('cells_data',{'deleted_in_revision_id':currentRevision.getId()},{'cell_id': cellId, 'created_in_revision_id' : cellRevisionId}) }
レコード更新
データの変更は削除のようなものです。 リビジョンが変更されていない場合、データは更新され、変更されている場合、deleted_in_revision_idフィールドが更新され、created_in_revision_idの新しいリビジョンIDで新しいレコードがcells_dataテーブルに挿入されます。
結論の代わりに
なぜなら バージョン管理が必要なテーブルのほとんどは、新しい構造に変換されました-長所と短所を強調できます。
長所
- すべての選択と挿入(言い換えると、選択と挿入)は、できるだけ早く、問題なくやり直されました。
- 必要なことはすべて行い、必要なことはほぼすべて行います
短所
- レコードの削除、更新はまだ少しきつすぎるため、より自動化されたスクリプトは問題ありません
- おそらく、(...)ではなく(...)などのクエリを使用して何かを行う必要があります。 ドキュメントのすべてのリビジョンをリストします