9

しばらくの間、Azure テーブル ストレージを十分に理解しようと努力してきました。一般的には、それがどのように機能するかは理解していますが、リレーショナル データベースの考え方を揺るがすのに本当に苦労しています。私は通常、例から最もよく学ぶので、誰かが私を助けてくれるかどうか疑問に思っています. リレーショナル データベースを使用して問題を解決するための簡単なセットアップの概要を説明します。Azure テーブル ストレージを使用するように変換する方法を教えてもらえますか?

簡単なメモを取るアプリがあり、ユーザーがいて、各ユーザーは必要な数のメモを持つことができ、各メモには必要な数のユーザー (所有者または閲覧者) を持つことができるとしましょう。リレーショナル データベースを使用してこれを展開する場合、次のように展開する可能性があります。

データベースについては、次のようなものから始めます。

CREATE TABLE [dbo].[Users](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Username] [nvarchar](20) NOT NULL)

CREATE TABLE [dbo].[UsersNotes](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [UserID] [int] NOT NULL,
    [NoteID] [int] NOT NULL)

CREATE TABLE [dbo].[Notes](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [NoteData] [nvarchar](max) NULL)        

次に、制約との関係Users.ID and UsersNotes.UserIDだけでなく、参照整合性を強化するための関係も設定します。Notes.ID and UsersNotes.NoteID

アプリケーションの場合、ORM に、これらのそれぞれに一致する名前プロパティを持ついくつかのエンティティを生成させます。

public class Users
{
    public int ID { get; set; }
    public String Username { get; set; }
}
// and so on and so forth

この設計はリレーショナル データベースに完全に依存していることに気付きました。私が探しているのは、Azure テーブル ストレージやその他の非リレーショナル データ ストレージ技術を使用するために、この一連の考え方を揺るがす方法についてのアドバイスです。

また、議論のために、私は Azure SDK をインストールし、それを試してみたと仮定しましょう。しかし、SDK の使用に関する私の実務知識は限られています。上記のようになります。良い出発点は、SDK を理解するのに役立ちます。参照ポイントがあるからです。

完全を期すために、

  • メモ データは最初に作成されたときに頻繁に変更され、時間の経過とともに徐々に減少します
  • ユーザーには多くのメモがあり、メモには複数のユーザー (同時ではなく閲覧者のみ) が含まれる場合があります。
  • かなり少数のユーザー (数百人未満) を想定していますが、かなりの数のメモ (ユーザーごとに数百人未満) を想定しています。
  • Usernameほとんどに対してクエリを実行し、ユーザーがアクセスできるメモを表示することを期待しています
  • また、メモを表示するときに、そのメモへのアクセス権を持つ他のユーザーを表示するために、逆引きを期待しています
4

3 に答える 3

5

いくつかの考え...

  1. 個別のエンティティを全体として考え、正規化手法を使用してそれらをさらに分解することは避けてください。
  2. エンティティごとに 1 つの識別子を考え出します。これにインデックスを付けると、正確なキー検索と範囲キー検索の両方が一致するようになります。
  3. Azure テーブル ストレージのスケーラビリティのニーズに合わせて、識別子を 2 つのセグメントに分割します。適切に分割する方法は、それ自体が別のトピックですが、通常、明確に定義された自然なセグメントにまたがって分割することで十分に機能します。

あなたの例では、2 つのエンティティはユーザーとメモになります。

ユーザーを一意に識別するには、UserId で十分です。ユーザーの範囲検索はあまり役に立たないかもしれません。ユーザー ID は、ここでは任意の固定長の値にすることができます。

メモを一意に識別するには、UserId + NoteId で十分です。メモ ID は、日付/タイムスタンプ + 一意性のための GUID のようなものです。このようなキーは、UserId と組み合わせてメモを一意に識別し、すべてのユーザーのメモまたは特定の期間のユーザーのメモに対する範囲検索を可能にします。

したがって、UserId = 「ABCD」の場合、NoteId は「20120801-00f64829-6044-4fbb-8b4e-ae82ae15096e」になります。

両方のエンティティを同じテーブルまたは異なるテーブルに格納できます。ここにいくつかの異なるアプローチがあります...</p>

各エンティティに独自のテーブルがある場合、

  • ユーザー パーティション キーは「ABCD」であり、行キーは実際には何でもかまいません。パーティション キーのみを検索します。

  • または、パーティション キーが「AB」で、行キーが「CD」の場合もあります。

    上記の両方とも、多数のユーザーに適しています。

  • または、パーティション キーが「*」で、行キーが「ABCD」の場合もあります。これは、少数のユーザーのセットでは非常にうまく機能し、ユーザーとメモの両方を同じテーブルに入れることができます。

メモ用

  • パーティション キーは「ABCD」、行キーは「20120801- 00f64829-6044-4fbb-8b4e-ae82ae15096e」になります。</p>

  • ここでの範囲検索は

    • On PartitionKey = "ABCD" で、ユーザーのすべてのメモを取得します。
    • PartitionKey = "ABCD" および RowKey >="20120801" および RowKey <= "20120901" で、日付範囲内のメモを取得します。

アップデート

私はあなたの質問を読み違え、ユーザーとノートの間の関係は 1 対多であると想定しました。多対多の関係があるため、重複を気にしない限り、モデル化するには 4 つのエンティティが必要です。(メモが短くて不変の場合、それらは複製でき、結合をモデル化する必要はありません)。

キーが異なるキー範囲にあり、簡単に区別できる場合は、1 つのテーブルに複数のエンティティを配置できます。ただし、実際には、特定の必要がない限り、これは一般的ではありませんが、通常は同じパーティションへのトランザクション書き込みです (そこには適用されません)。

したがって、単一のテーブル スキーマは次のようになります。複数のテーブルの場合、パーティション キーのプレフィックスが削除される可能性があります。

  • これを 3 つのテーブルでモデル化することもできます。1 つはユーザー用、もう 1 つはメモ用、もう 1 つは双方向の関係用です。
  • これを部分的に SQL で、部分的に Azure ストレージでモデル化することもできます。BLOB またはテーブル内のメモとユーザー データ、および SQL 内のリレーションシップ。

.

Entity        Partition Key              Row Key            
User          “U” + UserId      
Note          “N” + NoteId(Date)         NodeId(GUID)
User Note     “X“  + UserId              NoteId(Date+GUID)
Note User     “Y“  + NoteId(Date+GUID)   UserId    

これらはいくつかの代替案であり、データとニーズに最も適したものを決定する必要があります。

まだ別の更新
実際には、UserNote エンティティの Note には 3 つのエンティティで十分なはずです。

UserId = GUID
および NoteId = Date+GUID の 場合

Entity      Partition Key  Row Key             Note  User           
User        UserId      
User Note   UserId         NoteId(Date+GUID)   Note          (Contains Note and can query for all notes for a user).
Note User   NoteId(Date)   NodeId(GUID)              UserId  (Can query for all Users of a note. Join on ‘User Note’ to get note.)  
于 2012-08-02T06:10:21.887 に答える
5

Azure テーブルは、オブジェクトのコレクションと考えることができます。

Azure テーブルの用語では、オブジェクトはエンティティです。

あなたの例を使用するには、ユーザーは TableStorageEntity から派生します。

Azure Table Storage はリレーショナルではありません。結合はありません。しかし、さまざまな言語でサポートされているクエリ言語である LINQ があります。そのため、結合操作と参照整合性はシステムによって提供されません。開発者はこれを行う必要があります。

いくつかの重要な利点:

(1) Azure テーブルは、数十億のエンティティを扱っている場合でも、パフォーマンスを維持するために複数のストレージ ノード間で自動的にスケーリングされます。(2) 3 回レプリケートされます (3) SLA が付属しています (4) テーブル サービス API は REST API に準拠しているため、Microsoft 以外のテクノロジからアクセスできます。

オブジェクトを Azure テーブルに格納できるようにするには、TableStorageEntity から派生させるだけです。

「Microsoft Azure テーブル仮想ラボ」を検索すると、詳細情報が見つかります。

以下のスニペットは、(1) パーティション キー (2) 行キーを無視します。しかし、これはあなたが心配する必要があるものです。2 つのキーは、リレーショナル テーブルの主キーと考えてください。

この 2 つのキーについては、非常に慎重に考える必要があります。それらがパフォーマンスを決定します。キーのセットは 1 つしか取得できないため、最適なパフォーマンスを得るには、データの正規化されていないコピーを保持する必要がある場合があります。

    public class Users : TableStorageEntity
    {
        public int ID { get; 設定; }
        public String Username { get; 設定; }
    }

ハンズオンをご覧ください。Azure テーブルは安価で使いやすいです。

于 2012-08-01T22:10:08.687 に答える
1

UsersNotes に ID があるのはなぜですか? 複合主キーとしての UserID、NoteID だけではないのはなぜですか?

つまり、それぞれ 2 つのプロパティを持つ 3 つのテーブルです。1 つ目は PartitionKey で、2 つ目は RowKey です。

NoteID をクエリして UserID を大量に取得することが予想される場合は、4 番目のテーブルを使用すると、RowKey を検索するよりも PartitionKey を検索する方が高速になります。また、トランザクションが少なくなるため、通常は安くなります。ただし、テーブルをロードするためのトランザクションがあります。

public class NotesUsers : TableStorageEntity
    {
        public int NoteID { get; set; }
        public int UserID { get; set; }
    }

また、Users テーブルの場合、それが一般的なクエリ条件である場合は、UserName を PartitionKey として使用します。

ATS では、宣言的な参照整合性はありません。アプリケーションですべてのデータ関係を適用する必要があります。2 つの部分からなる複合キー。RowKey での検索は、スキャンに似ています (シークではありません)。PartitionKey での検索はシークに似ています。

しかし、私はSQLに行きます。メモが誰かが入力している場合、それは比較的少量のデータです。そして、それはリレーショナル データです。

于 2012-08-02T13:27:33.023 に答える