[AWS] IoTシステムでユースケースの追加によりDynamoDBの再設計が必要となった話

AWSのマネージドサービスを利用したIoTシステムの導入にて、追加で発生したビジネス上のユースケースに既存のDynamoDBのテーブル設計では対応ができなくなったため再設計が必要となった、というケースがあったためご紹介します。
2019.11.26

こんにちは。CX事業本部の若槻です。

今回はAWSのマネージドサービス(IoT Core、Lambda、DynamoDBなど)を利用したIoTシステムの導入にて、追加で発生したビジネス上のユースケースに既存のDynamoDBのテーブル設計では対応ができなくなったため再設計が必要となった、というケースがあったためご紹介します。

※本稿での説明のために一部単純化、例による置き換えを行っています。

どんなシステムか

戸建て住宅の設備(例:玄関の扉)にIoTデバイスを設置し、設備が最後に利用された時刻(例:扉が最後に開閉された時刻)をDynamoDBに記録するサービスを提供するシステムです。

DynamoDBのプロパティは以下のようになります。

  • placeId(住宅の識別値)
  • placeName(住宅の名称)
  • deviceId(IoTデバイスの識別値)
  • lastOpenCloseAt(最終開閉時刻)

DynamoDBのテーブルには以下のようにデータが格納されます。

placeId placeName deviceId lastOpenCloseAt
place001 住宅A device001 1574599548
place002 住宅B device002 1574600014
place003 住宅C device003 1574519724

キー・インデックスの指定は以下のようになります。ソートキーの指定はないため、プライマリキーはplaceIdのみとなります。

  • パーティションキー:placeId
  • ソートキー:なし

DynamoDBでデータが更新されるまでの一連の流れは以下のようになります。

  1. IoTデバイスが玄関扉の開閉を検知する
  2. IoTデバイスからAWSへ開閉時刻が送信される
  3. DynamoDBのテーブルに対してパーティションキーであるplaceIdをもとに更新対象のデータの検索が行われる
  4. 更新対象のデータのlastOpenCloseAtが更新される

追加のユースケースと、それによりDynamoDB観点で何が対応できなくなるのか

さて、ここで追加のユースケースとして「表口と裏口の2つの玄関を持つ住宅」に対しても同システムで対応ができるかどうか検討することとなりました。 その場合は表口と裏口のそれぞれの玄関にIoTデバイスを設置し、それぞれの最終開閉時刻を記録する必要があります。

当初の想定では、システムの対象となる住宅は1つの玄関(=1つのIoTデバイス)を持つケースのみであり、placeIddeviceId1対1の関係であったため、問題なく対応できていました。 しかし、追加のユースケースでは1つの住宅に2つの玄関があるため、placeIddeviceId1対2の関係となります。この場合はどうなるでしょうか?結論から言いますと、既存のテーブル設計では対応は不可となります。

[理想]としては以下のように住宅Cの表口(device003)と裏口(device004)の両方のIoTデバイスのデータが既存のテーブルに登録できると良いでしょう。

placeId placeName deviceId lastOpenCloseAt
place001 住宅A device001 1574599548
place002 住宅B device002 1574600014
place003 住宅C device003 1574519724
place003 住宅C device004 1574607363

しかし[実際]には以下のように既に登録されているdevice003のデータにdevice004のデータが上書きされる動作となります。

placeId placeName deviceId lastOpenCloseAt
place001 住宅A device001 1574599548
place002 住宅B device002 1574600014
place003 住宅C device004 1574607363

これは、プライマリキーであるplaceIdは同じテーブル内で値がユニークである必要があるため、同じデータとして扱われてしまったためです。

よってテーブル設計においてキー・インデックスの指定を以下のように再設計する必要があります。

  • パーティションキー:placeId
  • ソートキー:deviceId

ソートキーにdeviceIdを指定することにより、placeId + deviceIdから成るプライマリキーが追加のユースケースにおいてもユニークな値となるため、既存の設計では対応ができなかったdevice003device004の両方のデータの登録が可能となります。

おわりに

すでにDynamoDBの利用経験がある方にとっては初級レベルの内容のエントリだと思いますが、わたしは業務でAWSに触れるのが初めてであったため既存のテーブル設計で何がだめなのか理解をするのに時間を要しました。

今回のケースを通して、データベースとして概念設計の時点でユースケースの洗い出しを入念に行うことが、拡張性のあるDynamoDBのシステムを作る上で大切であることを実感しました。

参考

以上