Go - Chancho - 4によるダイナモ


最後に、複合主キーがどのようにしてダイナモを照会する能力を改善できるかを見た.今回は、インデックスがどのように我々のアクセスパターンでさらに我々を助けることができるかに集中します.
ダイナモのエピソード3のエピソードでは、我々はオーバーシンプルなファイルシステムモデルを構築しました.そのファイルシステムから1つのアイテムを共有しましょう.そうすれば、私たちがどのように見えたかに関して同じページにあります.
ディレクトリ
ファイル名
サイズ
財源
2017年PDF
1 MB
もし思い出したら、以下のような方法でファイルシステムを問い合わせることができました.
  • ディレクトリから一つのファイルをください
  • ディレクトリを全部ください
  • ファイルのいくつかは自分の名前で年を持っているという事実のおかげで、我々は与えられた日付より古い/若いファイルを得ることができます.Look here how we did it .
    我々がステージングに関してこれをテストしているように、製品人は我々の肩を見て、我々が創造時間に基づいて質問しているのを見ます、そして、彼女は絶対にそれを愛しています.つのことを除いて.

    クライアントの名前をファイルの作成日にすることは本当に期待できません


    今、私たちは追加の要件があります.作成日時に基づいてディレクトリ内のファイルを並べ替える必要があります.これは新しいアクセスパターンです.
    これはSQLではありません.WHERE and ORDER BY 節とクエリを追加作業なしで何か.DynamoDBのこの仕事のためのツールはインデックスです.

    インデックス


    DynamoDBのテーブルは、メインパーティションとソートキーのペアだけを持つことができます.これは、主キーと呼ばれます.それらはクエリのエントリポイントであるので重要です.
    しかし、なぜ彼らはエントリポイントですか?その質問に答えるために、ダイナモがどのようにデータを保存するかを考えましょう.まず、どのパーティションデータが格納されているかを決定するのに使用されるパーティションキーがあります.DynamoDBはパーティションキーに基づいてハッシュ関数を計算し、そのパーティションを検索します.同じパーティションキー(いわゆる項目コレクション)を共有するすべての項目は、単一のB - treeデータ構造内に格納されます.B - treeについて重要なことは、ソートされた順序でデータを問い合わせることができることです.並べ替えキーは、項目がツリー内でソートされる基準であるため、ここで重要です.見てみましょう.

    私はB - treeの代わりにバイナリ検索木を使いました、しかし、彼らはソート可能であるのと同じ特性を共有します、そして、これは話題のまわりで直観を構築するのに十分です.
    上の画像に対応するデータをここに示します.
    ディレクトリ( PK )
    ファイル名( sk )
    サイズ
    創造する
    写真
    バイク.PNG
    1.2 MB
    2017 - 03 - 04 00 : 00 : 00
    写真
    アパート.jpg
    4 MB
    2018 - 06 - 25 00 : 00 : 00 + UTC
    写真
    おじいちゃん.PNG
    3 MB
    2019 - 04 - 01 00 : 00 : 00
    写真
    キッズ.PNG
    3 MB
    2020 - 01 - 10 00 : 00 : 00 + UTC
    私たちのエントリポイントここからアイテムを取得する機能ですphotos ディレクトリとファイル名でソートします.これは、木によってのみソートできるように構成されているため、画像に正確に反映されますfilename . 別のエントリポイントを持ちたいなら、インデックスを導入する必要があります.
    インデックスは、追加のパーティションキーと並べ替えキーを導入することによってテーブルを照会する能力を強化します.
    Dynamodbには2種類の指標が存在する.二次とは、主キーに加えていることを意味します.

    ローカル二次指標


    主キーと同じパーティションキーが異なるソートキーです.これにより、追加属性で項目をソートできます.そのダイナモは、追加の再編成ツリーを格納する必要があります.それぞれの並べ替えパターンは、それ自身のツリーを持つ必要があります.
    追加のアクセスパターンはcreated_at 属性.これはcreated_at . その周りの頭をワープするイメージを見てみましょう.

    LSIはテーブル自体と同じパーティションキーを持つ必要があります.これがローカルなのです.私たちは、同じパーティションを使用して、プライマリソートキーとソートキーを見つけることができます.LSIの重要な制限は、テーブルの作成時に作成する必要があることである.つのテーブルに最大5つのLSIを持つことができます.

    グローバル二次指数


    GSIは異なります.これは任意のパーティションキーと並べ替えキーを同じテーブルにすることができます.パーティションキーがどこにあるかインデックスを作りましょうsize and filename ソートキーです.これは、そのサイズで写真をグループ化するクエリを行うことができます.

    インデックスのパーティションキーが全く異なっているので、インデックスを主キーに近づける可能性はもはやありません.新しいデータ構造を構築する必要がある.そういうわけで、このインデックスは世界的です.GSISは重要なので、あなたが想像するどんな方法ででもテーブルを問い合わせることができます.LSISと対照的に、GSISはいつでもテーブル寿命で作成されることができます.テーブルあたり最大20 GSsがあります.

    データベースレイアウト


    我々はビジネスの問題を解決することに集中し、我々はcreated_at .
    Resources:
      FileSystemTable:
        Type: AWS::DynamoDB::Table
        Properties:
          AttributeDefinitions:
            - AttributeName: directory
              AttributeType: S
            - AttributeName: filename
              AttributeType: S
            - AttributeName: created_at
              AttributeType: S
          KeySchema:
            - AttributeName: directory
              KeyType: HASH
            - AttributeName: filename
              KeyType: RANGE
          LocalSecondaryIndexes:
            - IndexName: ByCreatedAt
              KeySchema:
                - AttributeName: directory
                  KeyType: HASH
                - AttributeName: created_at
                  KeyType: RANGE
              Projection:
                ProjectionType: ALL
          BillingMode: PAY_PER_REQUEST
          TableName: FileSystemTable
    
    これは3番目のエピソードで以前にあったことと非常によく似ています.最初の違いは、私たちには新しい大きなセクションがあるということですLocalSecondaryIndexes インデックスが生きるところ.私はそれを呼んだByCreatedAt これが基本的に私がしたいことだからです.我々が中を見るならば、我々は複合プライマリキー定義と非常に類似した何かを見ます.があるKeySchema with RANGE and HASH キー.第2の違いは、新しい属性定義があるということです.だってRANGE キーオブザCreatedAt インデックス使用created_at 属性を定義する必要があります.
    type item struct {
        Directory string    `dynamodbav:"directory"`
        Filename  string    `dynamodbav:"filename"`
        Size      string    `dynamodbav:"size"`
        CreatedAt time.Time `dynamodbav:"created_at"`
    }
    
    The item も変更.新しい属性CreatedAt .

    1月19日から撮影された写真


    すべてのクエリの初期設定は同じです.ちょうどです.
    ctx := context.Background()
    tableName := "FileSystemTable"
    db, cleanup := dynamo.SetupTable(t, ctx, tableName, "./template.yml")
    defer cleanup()
    
    ではキー条件式を作りましょう.
    expr, err := expression.NewBuilder().
      WithKeyCondition(
        expression.KeyAnd(
          expression.KeyEqual(
            expression.Key("directory"),
            expression.Value("photos"),
            ),
          expression.KeyGreaterThanEqual(
            expression.Key("created_at"),
            expression.Value(time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)),
          ))).
      Build()
    
    クエリの正確なディレクトリを提供する必要があります.また、私はKeyGreaterThanEqual インデックスを利用するために.しかし、この式の観点から、インデックスは見えません.テーブルと仮想的にdirectory パーティションキーとcreated_at ソートキーでも有効な式です.ここでのポイントは、テーブルの上に多くの並べ替えキーを持つことができないということです.そのためにインデックスを使用する必要がありますが、別の並べ替えキーとしての種類の作業があります.
    out, err := db.QueryWithContext(ctx, &dynamodb.QueryInput{
      ExpressionAttributeNames:  expr.Names(),
      ExpressionAttributeValues: expr.Values(),
      KeyConditionExpression:    expr.KeyCondition(),
      TableName:                 aws.String(table),
      IndexName:                 aws.String("ByCreatedAt"),
    })
    assert.Len(t, out.Items, 2)
    
    ご覧の通り、我々は我々が使用していることを指定する必要がありますByCreatedAt インデックス.我々がそれを指定しないならば、DynamoDBはキー条件式がソートキーを欠いていると不平を言いますfilename ) を返します.created_at ). 結局、私は結果が2つのアイテムから成るかどうかチェックしています.

    2月18日から2018年まで撮影された写真


    クエリは、最初の問い合わせと同じように見えます(したがって、I ' imをスキップします)、しかし、このクエリを構築するために使用されるキー条件式は、私があなたに見せたかった新しい演算子を使用します.
    expr, err := expression.NewBuilder().
      WithKeyCondition(
        expression.KeyAnd(
          expression.KeyEqual(
            expression.Key("directory"),
            expression.Value("photos"),
          ),
          expression.KeyBetween(
            expression.Key("created_at"),
            expression.Value(
              time.Date(2017, 1, 1, 0, 0, 0, 0, time.UTC)),
            expression.Value(
              time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC))))).
      Build()
    
    それは簡単です-あなただけの検索のための下限と上限を設定する必要があります、それはすべてです-あなたは2017年から2018年に写真を取得します.

    最新の写真


    インデックスは、並べ替えキーでソートされた順序で項目を格納するためです(インデックスの)-新しい方法でデータにアクセスできます.パーティションキーのみを指定するキー条件式が必要です.
    expr, err := expression.NewBuilder().
      WithKeyCondition(expression.KeyEqual(expression.Key("directory"), expression.Value("photos"))).
      Build()
    
    キーコンディション式が単純になったので、クエリー自体は少し複雑になりました.
    out, err := db.QueryWithContext(ctx, &dynamodb.QueryInput{
      ExpressionAttributeNames:  expr.Names(),
      ExpressionAttributeValues: expr.Values(),
      KeyConditionExpression:    expr.KeyCondition(),
      TableName:                 aws.String(table),
      IndexName:                 aws.String("ByCreatedAt"),
      ScanIndexForward:          aws.Bool(false),
      Limit:                     aws.Int64(1),
    })
    
    まず最初にインデックスを横断しないことを指定する必要があります.デフォルトインデックスでデータを昇順に保持していますScanIndexForward パラメータ次に、クエリ結果を単一の項目に制限します.そのビットなしで-我々は、最新のものから古いものまですべての写真を返すでしょう.
    最後に、我々が得たアイテムが本当に最新のものかどうか確かめる.
    var items []item
    err =  dynamodbattribute.UnmarshalListOfMaps(out.Items, &items)
    assert.Equal(t, 2020, items[0].CreatedAt.Year())
    

    概要


    このエピソードはインデックスについてでした.最初に我々は彼らがどのように働くかについて直観を構築しました、そして、我々は追加属性によって質問するために地方の二次インデックスを使用しました.
    インデックスは、Dynamodbの重要な概念です、そして、より複雑なデータモデルで働くとき、我々は彼らのより多くを見ます.
    もう一度-私はこのリポジトリをクローン化し、自分でクエリを再生する招待!