6

私は Google App Engine Java を試していますが、一意の制約がないために問題が発生しています。私はこの記事を読んでおり、このブログは同様のものを実装する方法を提案しています。私のバックグラウンドは MySQL です。一意の制約なしでデータストアに移動すると、以前は値の重複について心配する必要がなく、新しい値を挿入する前に各値をチェックする必要がなかったので、まだエラーの余地があります。

「いいえ、スキーマの作成中に一意を指定することはできません。」

-- David Underhillが GAE と一意の制約について語っています (リンクを投稿)

一意または主キーに似たものを実装するために何を使用していますか?

通常のRDBのように機能する低レベルのAPIを使用して作成された抽象データストアレイヤーについて聞いたことがありますが、無料ではありませんでした(ただし、ソフトウェアの名前は覚えていません)

私の問題の概略図

sNo = biggest serial_number in the db
sNo++
Insert new entry with sNo as serial_number value //checkpoint
User adds data pertaining to current serial_number 
Update entry with data where serial_number is sNo 

ただし、3 行目 (チェックポイント) で、2 人のユーザーが同じ sNo を追加する可能性があると思います。そして、それが私がappengineで作業するのを妨げているものです.

4

4 に答える 4

12

従来の RDB から App Engine のような BigTable に似たデータストアへの移行について話していると、このような質問や他の同様の質問がよく出てきます。

データストアが一意のキーをサポートしていない理由について話し合うことは、データ ストレージ スキームについて考える際の心構えを示すため、しばしば役立ちます。一意の制約が使用できない理由は、スケーラビリティが大幅に制限されるためです。あなたが言ったように、制約を適用することは、そのプロパティの他のすべてのエンティティをチェックすることを意味します。コードで手動で実行するか、データストアがバックグラウンドで自動的に実行するかに関係なく、実行する必要があるため、パフォーマンスが低下します。いくつかの最適化を行うことはできますが、それでも何らかの方法で行う必要があります。

あなたの質問への答えは、なぜその一意の制約が必要なのかを本当に考えることです。

次に、キーはデータストアに存在し、単純な一意の制約を適用する優れた方法であることを覚えておいてください。

my_user = MyUser(key_name=users.get_current_user().email())
my_user.put()

これにより、そのメールで二度と作成されないことが保証さMyUserれ、そのメールですばやく取得することもできMyUserます。

my_user = MyUser.get(users.get_current_user().email())

Python ランタイムでは、次のこともできます。

my_user = MyUser.get_or_create(key_name=users.get_current_user().email())

その電子メールでユーザーを挿入または取得します。

ただし、それより複雑なものはスケーラブルではありません。したがって、そのプロパティをグローバルに一意にする必要があるかどうか、またはその一意の制約の必要性を取り除く方法があるかどうかを本当に考えてください。多くの場合、いくつかの小さな回避策で、そのプロパティが一意である必要はありませんでした。

于 2010-10-04T13:39:56.263 に答える
4

一意の ID を強制したり、エンティティのセット全体をクエリして現在最大のシリアル番号を調べたりする必要なく、製品の一意のシリアル番号を生成できます。トランザクションとシングルトン エンティティを使用して、「次の」シリアル番号を生成できます。操作はトランザクション内で行われるため、2 つの製品が同じシリアル番号を取得することはありません。

ただし、このアプローチは潜在的なパフォーマンス チョークポイントとなり、アプリケーションのスケーラビリティを制限します。競合が発生するほど頻繁に新しいシリアル番号が作成されない場合は、うまくいく可能性があります。

編集:明確にするために、割り当てられる現在または次のシリアル番号を保持するシングルトンは、実際にシリアル番号が割り当てられているエンティティから完全に独立しています。すべてがエンティティ グループの一部である必要はありません。同じメカニズムを使用して複数のモデルからエンティティを取得し、新しい一意のシリアル番号を取得できます。

Java についてはサンプル コードを提供できるほどよく覚えていません。また、私の Python の例はあなたにとって意味がないかもしれませんが、アイデアを説明するための疑似コードを次に示します。

  1. 新しいインベントリ アイテムを作成するリクエストを受け取ります。
  2. 取引を入力します。
  3. SerialNumber モデルの単一エンティティの現在の値を取得します。
  4. 値を増やしてデータベースに書き込む
  5. トランザクションを終了すると値が返されます。

ここで、実際に在庫品目を作成し、それを新しいシリアル番号とともに保存するすべての作業を行うコードは、トランザクションで実行する必要はありません。

警告: 上で述べたように、一度に作成できるシリアル番号は 1 つだけであるため、これはパフォーマンスの大きなボトルネックになる可能性があります。ただし、生成したシリアル番号が一意であり、使用されていないことを確認できます。

于 2010-10-04T14:55:45.133 に答える
3

ユーザーがタイムスロットを予約する必要があるアプリケーションで、これと同じ問題が発生しました。ユーザーが同じタイムスロットを同時に要求することを期待しながら、一意のタイムスロット エンティティを 1 つだけ「挿入」する必要がありました。

App Engine でこれを行う方法の例を分離し、それについてブログを書きました。ブログ投稿には、Datastore と Objectify を使用した正規のコード例があります。(ところで、JDOを避けることをお勧めします。)

また、 2 人のユーザーを同じリソースの予約に進めることができるライブ デモンストレーションも展開しました。このデモでは、クリックごとにアプリ エンジン データストアの正確な動作を体験できます。

一意の制約の動作を探している場合は、これらが役立つはずです。

-ブロック

于 2011-06-19T21:48:24.507 に答える