単一表設計による階層データのモデリング


あなたが賃貸用のオフィススペースを提供する不動産会社のために働いていると想像してください.すべての建物は、パラメータの無数を測定するセンサーの多くは、それらのスマートな新しいものです.これらのセンサーを管理するシステムを設計する必要があります.

Access patterns
まず最初に、IDEを開く前に、このアプリケーションで何をするかを知る必要があります.可能なすべての行動を列挙しましょう.
センサーを登録する必要があります.新しいセンサーを次のように導入します.
Register(Sensor{ID: "humidity-sensor-1", City: "Poznan", Building: "A", Floor: "3", Room: "112"})
成功した登録の後、私は新しいセンサー読書を書く可能性があると思っています.
NewReading(Reading{SensorID: "humidity-sensor-1", Value: "0.67"})
センサーが登録され、既にDBにいくつかのデータポイントがあります.どのように、我々はシステムのユーザーにこれを表示できますか?私は、場所からセンサーを得ることができたいです.例えば、
  • リスボンですべてのセンサーをください.
  • 4階のビルDでベルリンのすべてのセンサーをください.
  • 432号室のA階2階にあるPozna Countのすべてのセンサーをください.
  • 次のようなAPIを考えています.
    GetSensors(Location{City: "Poznań", Building: "A", Floor: "2"})
    GetSensors(Location{City: "Poznań", Building: "D", Floor: "1", Room: "123"})
    
    私が捜したと言いましょう:「ポザンラ、ビルディングA」と25の異なるセンサーのリストを受けました.UIに関して-私は与えられたセンサーをクリックして、このセンサーの10の最新の測定値でセンサーに関する詳細な情報を受け取りたいです.私は、呼び出しを想像します:
    Get("carbon-monoxide-sensor-2", 10)
    
    それは十分簡単です.つの異なるタイプで動作する4つの異なる機能があります.

    Table design
    我々は、我々が成し遂げたいものを知っています.方法を定義する時間です.どのように我々はそれを実装できますか?私は、このエピソードを2つの異なるもののための運動にしたいです:
  • シングルテーブルデザイン
  • 階層的データのモデル化

  • Single Table Design
    単一のテーブルデザインのアイデアは、単一のクエリを持つエンティティの種類をDynamoDBに取得することです.多くのテーブルを同時にクエリする可能性がないので、別の型が一緒に1つのテーブル内に格納する必要があります.

    Modeling hierarchical data
    階層の異なるレベルでデータを取得することができることはいくつかの考えを先行する必要があります.我々は、使用能力を活用するつもりですbegins_with ソートキーのメソッド.

    Sensors Table
    京大理
    sk

    シティ
    ビル
    フロア
    部屋
    種類
    センサは、S 1
    読誦
    2
    センサは、S 1
    記事を読む
    3
    センサは、S 1
    記事を読む
    5
    センサは、S 1
    記事を読む
    3
    センサは、S 1
    センサ情報
    ポザナ
    エー
    2
    13
    ガス
    私はテーブルにデータを入れる最初の試みをスケッチした.最初に気づくべきことは、パーティションキーとソートキーがドメイン知識を伝える名前を持っていないことです.ただ一つのテーブルデザインでは、異なるタイプのエンティティがあるため、PKとSKは異なるアイテムタイプに対して異なることを意味します.
    このレイアウトでは、センサーを照会し、最新の情報と共に詳細な情報を得ることができます.これが私たちが単一のテーブル設計をしている理由です.異なる種類のエンティティを取得するには、一度だけDynamODBを問い合わせる必要があります.
    これは今までのところ悪いことではありませんが、同じ場所を共有している多くのセンサーについて質問しています.前に言ったようにbegins_with ソートキーで.以下のようなクエリを行います.
    Query(PK="Poznań", SKbeginswith="A#-1") -> all sensors from garage in building A in Poznań
    Query(PK="Berlin") -> all sensors in Berlin
    Query(PK="Lisbon", SKbeginswith="F#3#102") -> all sensors in Lisbon in the building F, room 102 on 3rd floor.
    
    そのためには、異なる属性の連結である追加の人工的な属性を導入する必要があります.
    まず最初にこのようなことをテーブルに書くだけです.
    京大理
    sk
    ID
    シティー・チェン
    位置は1
    S 1
    現在、私は与えられた場所でセンサーを照会するための要件を満たすことができます.覚えておくべき一つのことは、同期する必要がある2つの項目があるということです.センサーとその場所についての詳細情報です.センサーを登録して、位置を変えることは、このアプローチによってより複雑です.なぜなら、これらの情報が分岐しないように、動的に2つの項目をtransodticallyに変更する必要があるからです.
    他のアイデアはグローバル二次インデックス(GSI)を使用することです.
    京大理
    sk

    シティ
    ビル
    フロア
    部屋
    種類
    ゲシェンPK
    ゲシェンsk
    センサは、S 1
    読誦
    2
    センサは、S 1
    記事を読む
    3
    センサは、S 1
    記事を読む
    5
    センサは、S 1
    記事を読む
    3
    センサは、S 1
    センサ情報
    ポザナ
    エー
    2
    13
    ガス
    ポザナ
    - 1
    与えられた場所にセンサーを問い合わせるたびに、GSIを使用します.ここで隠しているのは、まだスパース指数と呼ばれる別の概念です.このインデックスは、いくつかの項目だけを含んでいるので、まばらです.そのインデックスを照会するか、またはスキャンするとき、我々はそれを持っているどんなアイテムも得ませんREAD# これらの項目がこのインデックスに含まれていないので、これらの項目がGsiSense PKとGSIRAN SK属性の値を持っていないため、これらの項目がSKに含まれます.
    どちらのアプローチが良いですか?テーブルの追加項目は、単に動作する非常に簡単なアプローチです.つの欠点は、センサーが登録されているか、または位置変更であるときに、2つのアイテムをトランザクション的に変更する必要があり、プログラムエラーがこのデータを分岐させる原因になることです.一方gsiがある.その利点は、私たちが場所を変えるとき、または、我々が新しいセンサーを登録するとき、1つのアイテムだけを変える必要があるということです.しかし、インデックスには余分なお金がかかり、そのデータはGSIにコピーされ、GSIからデータを読むときには、一貫性のない読み出しはオプションではないことを意味します.GSIからのすべての読み取りは、最終的に一貫しています.

    Summary
    今のところ十分な仕事をしたと思う.この話題を2話に分けてみよう.これはDynamodbについてでした、次に、1は試みでより多くです.しかしながら、要約するために、我々のアクセスパターンが何であるかを知っています.さらに、我々は、各々のアプローチの短所と長所が何であるかについて学びました.次のエピソードに対して提案するのは、最初に我々が取得したい動作を定義する単体テストを書くことです.それから、我々は両方の方法を実行するつもりです:追加項目とGSIで.