パーティションの選択


previous post 私はDynamODBのSQLのような新しいAPIを使用してデモテーブルにいくつかの行を挿入します.私は項目を選択してチェックしましたが、順序ごとに制限されました.ここでは理解することが最も重要です.Partiql(「Particle」のように発音し、任意の種類のディスレクシアを回避するのに役立ちます)は、INSERT/UPDATE/DELETE/SELECTを持つステートメントを解析し、既に知っているNOSQL APIを呼び出します(put/get/update/delete item、query and scan).SQLのように見えますが、SQLは、物理モデル上の論理層であるリレーショナルテーブルやビューのような一連の行の操作を宣言する言語です.RDBMSでは、物理的なレイアウトではなく、ビジネスのニーズに応じてSQLクエリを構築します.もちろん、物理的なレイアウト(インデックス化、分割のような)もこのアクセスのために最適化されます、しかし、これは独立してされます.あなたのステートメントを書くときに、どのような操作が起こるかを知る必要があります.DynamoDBのすべてのシンプルさとスケーラビリティは、物理的なレイアウトにマッチする制限されたAPI上にあります.
  • getitemパーティション剪定+ユニークなハッシュ/インデックスアクセスを1つの項目を取得する
  • クエリはパーティションの剪定+インデックスアクセスをソートした項目の範囲を取得します
  • すべての項目を取得するために、すべてのパーティションを読み込みます.
  • もちろん、コストは異なります.DynamoDB APIを使用すると、別の操作を呼び出しているかを知っています.Partiqlを使用すると、あなたが何をしているかを知る必要がありますが、同じステートメントを実行します.基本的に、パーティション(ハッシュ)キーに等値述語を持たない場合は、すべてのパーティション(スキャン)を読まなければなりません.あなたがパーティション(Running)キーの上で等値述語を持っているならば、あなたがパーティション剪定(質問)から利益を得るソート(範囲)キーの不平等.これはハッシュ関数であることを知っているときに明らかですが、データモデルを知らない場合はエラーが発生します.DynamoDB APIを使用すると、大きなテーブルの“スキャン”を入力するときに指を傷つけるので、それを防ぐことができます.

    スキャン


    それで、あなたが望むものが実際にすべてのアイテムを得るならば、あなたが彼らのすべてを必要とするか、多分彼らの小さい部分だけを除外するために、あなたは走査を望みます.はい、すべてを読み取りますが、それはあなたのテーブルの大部分を読むための最も効率的なアクセスです.つのRCUで多くのアイテムを得ることができるので.getitemで同じ(すべてのアイテムを得る)ことをすることはアイテムにつき1つのRCUを要するでしょう(私はここで強い一貫性と小さいアイテムを仮定します).基本的に、OLTPワークロード(多くのユーザーが少数のアイテムを読んでいる)のために、あなたは大きなテーブルでスキャンを避けます.DynamoDBはキー値ストアです:ゴールはキーでアクセスすることです.いくつかの報告やデータをエクスポートするには、高価な(時間とRCUで)が、頻繁に行われないスキャンすることがあります.
    前の記事で見たように、すべての属性を持つすべての項目を取得するには、テーブル全体をスキャンします.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select * from Demo"
    
    {"Items":[
    {"MyKeyPart":{"N":"2"},"MyUnstructuredData":{"S":"a"},"MyKeySort":{"N":"1"}},
    {"MyKeyPart":{"N":"2"},"MyUnstructuredData":{"S":"use parameters when embedding SQL in programs"},"MyKeySort":{"N":"2"}},
    {"MyKeyPart":{"N":"2"},"MyUnstructuredData":{"S":"c"},"MyKeySort":{"N":"3"}},
    {"MyKeyPart":{"N":"2"},"MyUnstructuredData":{"S":"d"},"MyKeySort":{"N":"4"}},
    {"MyKeyPart":{"N":"2"},"MyUnstructuredData":{"S":"e"},"MyKeySort":{"N":"5"}},
    {"MyKeyPart":{"N":"1"},"MyUnstructuredData":{"S":"here is my first insert :)"},"MyKeySort":{"N":"1"}}
    ]}
    
    主キー(または複合ハッシュ/ソートキーの場合のハッシュ部分)に等値述語がない限り、SELECTはスキャンを行います.私は「平等」について言及しました、私たちは、多くの等値述語または等しい値のリストがあるとき、後でわかります.私たちは後に、おそらく更なるポストにおいて、二次インデックスで起こることがわかるでしょう.とにかく、これはRDBMSではありません.テーブルを照会すると、インデックスから読み取るアクセスを最適化するクエリプランナーはありません.二次索引でアクセスする場合は、FROM句にインデックス名を記載しなければなりません.
    以前のポストで見たことがあるのは、スキャンとして、DynamOdbが複数のパーティションから取得したときに、行をソートしないため、パーティションキーを順番に持つことはできません.したがって、基本的には、パーティションキーのWHERE句を持たない場合の順序はありません.
    
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo order by MyKeyPart"
    
    An error occurred (ValidationException) when calling the ExecuteStatement operation: Must have WHERE clause in the statement when using ORDER BY clause.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo order by MyKeySort"
    
    An error occurred (ValidationException) when calling the ExecuteStatement operation: Must have WHERE clause in the statement when using ORDER BY clause.
    
    

    クエリ


    その後、1つのパーティションのみを問い合わせる場合、これはスキャンではなくクエリーです.ここでは、ハッシュ関数を使用して1つのパーティションにマップするMyKeyPart = 2の項目だけを選択する例を示します.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo where MyKeyPart = 2"
    
    {"Items":[{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"2"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"3"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"4"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"5"}}]}
    
    アイテムは、それが保存され、各パーティション内で物理的にretreivedされているので、順序のない場合でもmyKeSortによって順序付けられます.しかし、SQLが宣言的な言語であるので、私はオーダーバイオーダーのない順序に依存しないほうが好きです.
    追加費用なしでそれをする正しい方法は、ここにあります:
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo where MyKeyPart = 2 order by MyKeySort"
    {"Items":[{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"2"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"3"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"4"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"5"}}]}
    
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo where MyKeyPart = 2 order by MyKeySort desc"
    {"Items":[{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"5"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"4"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"3"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"2"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"1"}}]}
    
    MyKeyPartの値が1つしかないので、myKeyPartを順番に置く必要はありませんでしたが、複数の値を指定する必要があります.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort \
    from Demo where MyKeyPart = 1  or MyKeyPart = 2 order by MyKeySort"
    
    An error occurred (ValidationException) when calling the ExecuteStatement operation: Must have hash key in ORDER BY clause when more than one hash key condition specified in WHERE clause.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort \
    from Demo where MyKeyPart = 1  or MyKeyPart = 2 order by MyKeyPart,MyKeyPart desc"
    
    {"Items":[{"MyKeyPart":{"N":"1"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"5"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"4"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"3"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"2"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"1"}}]}
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort \
    from Demo where MyKeyPart = 1  or MyKeyPart = 2 order by MyKeyPart desc,MyKeyPart"
    
    {"Items":[{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"5"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"4"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"3"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"2"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"1"},"MyKeySort":{"N":"1"}}]}
    
    
    複数の値を持つこのクエリが、スキャンではなくクエリとして実行されていることがわかります.彼らが複数のパーティションから来るならば、どうですか?
    値の数が事前によく知られている(ここでは“1”と“2”)とき、これは可能です.もちろん、これはコストを掛けるでしょう.例えば、1から5までの値を挿入したことを知っているので、すべてのアイテムを入手できます.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort \
    from Demo where MyKeyPart in [1,2,3,4,5] order by MyKeyPart,MyKeySort"
    
    {"Items":[{"MyKeyPart":{"N":"1"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"2"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"3"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"4"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"5"}}]}
    
    それで、私は現在ソートされるすべてのアイテムを得ることができます?はい、しかし、それは1つずつを検索するので、スキャンより高いコストです.私はここでスキャンするのは安くなりますが、両方の操作のコストを見積もるし、安価を選択するオプティマイザはありません.しかし、少なくとも、コストはリストのキー値の数に比例して予測可能です.
    私は不等式を使うことができません、あるいは、彼らは範囲で働きます、そして、この質問アクセスは既知の値だけでされることができます.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo where MyKeyPart between 2 and 2 order by MyKeyPart,MyKeySort"
    
    An error occurred (ValidationException) when calling the ExecuteStatement operation: Must have at least one non-optional hash key condition in WHERE clause when using ORDER BY clause.
    
    ここで、数学が、それが平等に等価であると私に話すとしても(「2と2の間のmyKeyPart」はmyKeyPart = 2と同じです)、それらの変換をするためにそこにオプティマイザがありません.ルールは基本です:値のセットをソートすることができます個別に照会することができますが、何か他のハッシュ関数でアクセスできない値の範囲と見なされます.
    どのように、私はこの行動について確実でありえますか?応答時間差が重要でない小さなテーブルがあります.最高の証拠は完全なテーブルスキャンが不可能であるときに何が起こるかを確認することです.スキャンを拒否するIAMポリシーがあります.
    私は、状態に関してDenyでユーザーを作成しました

    このユーザープロファイルで次のように実行します.
    
    [[email protected] aws]$ aws --profile noscan dynamodb execute-statement --statement "select MyKeyPart,MyKeySort \
    from Demo"
    
    An error occurred (AccessDeniedException) when calling the ExecuteStatement operation: User: arn:aws:iam::802756008554:user/ddb-noscan is not authorized to perform: dynamodb:PartiQLSelect on resource: arn:aws:dynamodb:eu-west-1:802756008554:table/Demo with an explicit deny
    
    [[email protected] aws]$ aws --profile noscan dynamodb execute-statement --statement "select MyKeyPart,MyKeySort \
    from Demo where MyKeyPart in [1,2,3,4,5]"                
    
    {"Items":[{"MyKeyPart":{"N":"1"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"2"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"3"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"4"}},{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"5"}}]}
    
    完全なテーブルスキャンが否定されるとき、5つの値のリストの上でWhereはまだ可能です.それは5クエリの代わりにスキャンの呼び出し.

    ページ


    MyKeyPart = 10と大きなサイズの属性を追加し、問い合わせを行います.
    
    $ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo where MyKeyPart=10"
    
    {"Items":[{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"1"}},{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"2"}},{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"3"}},{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"4"}},{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"5"}}],"NextToken":"CS4sUIPi4Efg7eSg4sGJZHJ09C/m8JWMwLXB+DF5n54EIBl6yuPZNAHfoRUFg7qgGg872qXswoXSZEI/XAIfvUPNisWSYGrPiquxLFakMecd6aF/ggaexxpKlhPS+ridkOXu8HoWIuWgSXFRBa32QmIXITRhrSMwuT1Q54+6Li6emcxvtpJfmxvxWf/yQkece5nqQIwH/EC3vAr1SZ4Pd537qexKejVHJ+2QrXALwG283UR/obWc53A2HTQ+G3cNeL4xOvVwp9gsOhlKxhsRrS+GqHRF0IHlGrpsdc0LkbMS1hISuagp/KZ0dqP/v7ejB6HsEHhFYZeKYZBoysTYTzhpB02NF3F4MSKp8QF4nO4vcq4="}
    
    私はいくつかの項目と非常に大きい“次のトークン”を取得します.
    次のページを次のトークンオプションで問い合わせることができます.
    
    $ ws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo where MyKeyPart=10 \
    --next-token CS4sUIPi4Efg7eSg4sGJZHJ09C/m8JWMwLXB+DF5n54EIBl6yuPZNAHfoRUFg7qgGg872qXswoXSZEI/XAIfvUPNisWSYGrPiquxLFakMecd6aF/ggaexxpKlhPS+ridkOXu8HoWIuWgSXFRBa32QmIXITRhrSMwuT1Q54+6Li6emcxvtpJfmxvxWf/yQkece5nqQIwH/EC3vAr1SZ4Pd537qexKejVHJ+2QrXALwG283UR/obWc53A2HTQ+G3cNeL4xOvVwp9gsOhlKxhsRrS+GqHRF0IHlGrpsdc0LkbMS1hISuagp/KZ0dqP/v7ejB6HsEHhFYZeKYZBoysTYTzhpB02NF3F4MSKp8QF4nO4vcq4="
    
    {"Items":[{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"6"}},{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"7"}},{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"8"}},{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"9"}},{"MyKeyPart":{"N":"10"},"MyKeySort":{"N":"10"}}],"NextToken":"FjHEA2wnIK74SlGaS6TiPSv2fEwfiZhJNHyxvJ+qG750oeKlqSNyx9IDdCUD+m2rSpodPIFJhYYQHXBM9sJed3k6qaA/aUk4s4DUlPvZHl7WAJ4rTY0AmNDUYBPqWyCV8FliSsGPtFTfj1A9T4zD1TU6uuvNIORY/zKHtsAjWzT4Jsg5y32MFcVOmOsDBhyWsQotFqxy1ErMGhJy3cQnEvy1P1KpQak6sflzp3sWLWzUgOXQB/xF1PXRtT8w/E1lPk26LnA/L2bA91nucuohN63hP3MVojPH0GkPCjZsx08wJTn4MEpqDArEREWO2XCkL/GI7vTtYw6GXRenKZoatSG55yKCVDkFRuw7cbK749mEIb6r6Xs="}
    
    繰り返しますが、これはカーソルがあるSQLデータベースとは全く異なりますが、これは小さなチャンクで項目の範囲を読み取るDynamoDBクエリに適しています.

    投影


    SELECT with *を使用して、項目全体のキーと属性(allRange属性のような)を取得し、属性のリストを指定してクエリプロジェクション(特定の属性のような)を行います.アグリゲーションはないし、カウント数を同等にできるとは思わない.可能ならばどうするかということです.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select count(*) from Demo"
    
    An error occurred (ValidationException) when calling the ExecuteStatement operation: Unexpected path component at 1:8
    
    これは明らかに支持されていない.
    によるとdocumentation 式は以下のようにします.
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort,size(MyUnstructuredData) from Demo where MyKeyPart=2 and size(MyUnstructuredData)>10"
    
    An error occurred (ValidationException) when calling the ExecuteStatement operation: Unexpected path component at 1:28
    
    明らかに、このsize ()関数はWHERE句だけで許可されています:
    
    [[email protected] aws]$ aws dynamodb execute-statement --statement "select MyKeyPart,MyKeySort from Demo where MyKeyPart=2 and size(MyUnstructuredData)>10"
    
    {"Items":[{"MyKeyPart":{"N":"2"},"MyKeySort":{"N":"2"}}]}
    
    要約してください.WHERE句でどの属性をフィルタリングするかを知っている必要があります.パーティションキーの等価性は単一のハッシュパーティションアクセスを許します.それなしで、それは時間を取ることができるスキャンとRCUの多くです(しかし、これは1 MBのPaginationに感謝します).next post それについて.