C#에서 DynamoDB에서 시계열 데이터를 GSI를 사용하여 범위 지정 및 검색

13797 단어 DynamoDBC#AWS
C#에서 Amazon DynamoDB에 저장된 시계열 데이터를 GSI(Global Secondary Index)를 사용하여 범위 지정 및 검색하는 방법입니다.

[사전 준비 1] 데이터



아래 구조의 데이터를 저장할 수 있도록,
[DynamoDBTable("SampleTable")]
public class Sample
{
    /// <summary>「SampleTable」テーブルのハッシュキー</summary>
    [DynamoDBHashKey]
    public string Id { get; set; }

    /// <summary>「SampleTable」テーブルのレンジキー</summary>
    [DynamoDBRangeKey]
    public string DateAndTime { get; set; }

    /// <summary>「Date-Time-index」GSI のハッシュキー</summary>
    [DynamoDBGlobalSecondaryIndexHashKey]
    public string Date { get; set; }

    /// <summary>「Date-Time-index」GSI のレンジキー</summary>
    [DynamoDBGlobalSecondaryIndexRangeKey]
    public string Time { get; set; }

    [DynamoDBProperty]
    public string Message { get; set; }

    public override string ToString()
    {
        return $"{Id} / {DateAndTime} / {Message}";
    }
}

AWS Console에서 Id , DateAndTime 를 키로 한 SampleTable 테이블을 준비합니다.


그런 다음 아래와 같이 SaveAsync 메서드를 사용하여 10개의 데이터를 만듭니다.
// DynamoDB にアクセスするためのオブジェクトを用意
using var client = new AmazonDynamoDBClient(RegionEndpoint.APNortheast1);
using var context = new DynamoDBContext(client);

// 10件のデータを作成
for (var i = 0; i < 10; i++)
{
    var now = DateTime.Now;

    await context.SaveAsync(new Sample
    {
        Id = $"{i % 3 + 1:D3}",
        DateAndTime = $"{now:yyyy-MM-dd HH:mm:ss.fff}",
        Date = $"{now:yyyy-MM-dd}",
        Time = $"{now:HH:mm:ss}",
        Message = $"メッセージ - {i + 1}"
    });

    // 保存される時間をずらしたいので 500 msec 待機
    await Task.Delay(500);
}

아래와 같이 ScanAsync 메소드를 사용해 모든 데이터를 취득합니다.
// 全データを取得
var listAll = await context.ScanAsync<Sample>(null).GetRemainingAsync();

Console.WriteLine("--- listAll");
listAll.OrderBy(n => n.DateAndTime).ToList().ForEach(Console.WriteLine);

그러면 아래와 같이 데이터를 얻을 수 있습니다.
--- listAll
001 / 2020-08-11 11:40:40.236 / メッセージ - 1
002 / 2020-08-11 11:40:41.224 / メッセージ - 2
003 / 2020-08-11 11:40:41.756 / メッセージ - 3
001 / 2020-08-11 11:40:42.293 / メッセージ - 4
002 / 2020-08-11 11:40:42.824 / メッセージ - 5
003 / 2020-08-11 11:40:43.355 / メッセージ - 6
001 / 2020-08-11 11:40:43.877 / メッセージ - 7
002 / 2020-08-11 11:40:44.412 / メッセージ - 8
003 / 2020-08-11 11:40:44.936 / メッセージ - 9
001 / 2020-08-11 11:40:45.458 / メッセージ - 10

[사전 준비 2] GSI



AWS Console에서는 다음과 같이 데이터가 저장되어 있는지 확인할 수 있습니다.


사전 준비가 끝나면 AWS Console에서 Date , Time 를 키로 한 Date-Time-index 인덱스(GSI)를 준비하여 날짜 및 시간을 범위 지정하여 검색할 수 있습니다.


이것으로 준비가 완료됩니다.

[시나리오 1] Id = 001의 데이터를 얻고 싶습니다.



아래와 같이 해시 키에 001 를 지정해 QueryAsync() 메소드를 사용해 데이터를 취득합니다.
var list01 = await context.QueryAsync<Sample>("001").GetRemainingAsync();

Console.WriteLine("--- list01");
list01.OrderBy(n => n.DateAndTime).ToList().ForEach(Console.WriteLine);

그러면 아래와 같이 데이터를 얻을 수 있습니다.
--- list01
001 / 2020-08-11 11:40:40.236 / メッセージ - 1
001 / 2020-08-11 11:40:42.293 / メッセージ - 4
001 / 2020-08-11 11:40:43.877 / メッセージ - 7
001 / 2020-08-11 11:40:45.458 / メッセージ - 10

Id가 001인 데이터만 검색할 수 있습니다.

[시나리오 2] 2020-08-11 의 11:40:42~11:40:43 의 데이터를 취득하고 싶다



아래와 같이 GSI 의 이름 Date-Time-index 를 지정해, 해시 키에 2020-08-11 를 지정해, 레인지 키에는 QueryOperator.Between11:40:42 - 11:40:43 를 지정해 QueryAsync() 메소드를 사용해 데이터를 취득 합니다.
var list02 = await context.QueryAsync<Sample>(
    "2020-08-11",
    QueryOperator.Between,
    new List<object>
    {
        "11:40:42",
        "11:40:43"
    },
    new DynamoDBOperationConfig
    {
        IndexName = "Date-Time-index" // 利用する GSI を指定
    }).GetRemainingAsync();

Console.WriteLine("--- list02");
list02.OrderBy(n => n.DateAndTime).ToList().ForEach(Console.WriteLine);

그러면 아래와 같이 데이터를 얻을 수 있습니다.
--- list02
001 / 2020-08-11 11:40:42.293 / メッセージ - 4
002 / 2020-08-11 11:40:42.824 / メッセージ - 5
003 / 2020-08-11 11:40:43.355 / メッセージ - 6
001 / 2020-08-11 11:40:43.877 / メッセージ - 7
SampleTable 테이블의 해시 키인 Id 를 넘어 11:40:42 - 11:40:43 의 데이터만을 취득할 수 있습니다.

사이고에게



GSI를 사용하여 날짜와 시간을 범위 지정하여 검색할 수 있었습니다.
다만, 코스트면의 고려나 NoSQL다운 설계에 대해서는 할 수 있을까라고 하면,

더 좋은 방법이 있다면 알려주세요 m(_ _)m

좋은 웹페이지 즐겨찾기