クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

DynamoDB のキー: クエリかスキャンか

このレッスンのあとで: クエリがスキャンより安い理由を、説明することができる。

55分のレッスンコマンドなし

注文を全部読むのか

ネットショップに、100万件の注文があります。ある客が、自分の注文を見たいと言いました。

店は、100万件を全部読んで探すのでしょうか。よくできた DynamoDB の表は、そうしません。クエリは、その客の注文へ直接行き、ほかは読みません。このレッスンでは、クエリがスキャンより安い理由と、答えの数の読み方を学びます。

このレッスンのゴール

メモ

クエリがスキャンより安い理由を、説明することができる。

キーワード

ことばいみ
パーティションキー項目をどこに保存するかを決める属性
ソートキー同じパーティションキーの中で、項目を並べる属性
キー条件クエリがキーに対して行う判定
クエリ1つのパーティションキーへ行く読み取り
スキャン表のすべての項目を見る読み取り
フィルター項目を読んだあとに行う判定

学生が入力するセルは、このプレビューでは空白です。

2つのキーが住所になる

この注文の表には、キーになる属性が2つあります。パーティションキーは customer です。サービスが項目をどこに保存するかを決めるので、1人の客の注文は、まとまって並びます。

ソートキーは order_id です。1人の客の注文を、順番に並べます。2つのキーが合わさって、項目がちょうど1つに決まります。同じ客の注文は何件もありますが、2つのキーが両方同じ注文はありません。

例: 注文の並び方

パーティションキー: customerソートキー: order_idほかの属性
sato1ramen、paid、total 4
sato2tea、new、total 2
sato3cake、paid、total 15
suzuki7ramen、paid、total 8
tanaka4tea、new、total 6
tanaka9ramen、paid、total 3

学生が入力するセルは、このプレビューでは空白です。

クエリは1か所へ、スキャンは全部へ

クエリは、パーティションキーを必ず指定します。指定しないと、サービスは ValidationException と HTTP 状態 400 で断ります。サービスはその客へ直接行き、その客の注文だけを読みます。

スキャンは、何も指定しません。表のすべての項目を、1件ずつ読みます。どちらの答えにも、Count と ScannedCount があります。Count は返した項目の数、ScannedCount は見た項目の数です。

実行: クエリとスキャン

コード: python
orders = [
    {"customer": {"S": "sato"}, "order_id": {"N": "1"}, "status": {"S": "paid"}},
    {"customer": {"S": "sato"}, "order_id": {"N": "2"}, "status": {"S": "new"}},
    {"customer": {"S": "sato"}, "order_id": {"N": "3"}, "status": {"S": "paid"}},
    {"customer": {"S": "suzuki"}, "order_id": {"N": "7"}, "status": {"S": "paid"}},
    {"customer": {"S": "tanaka"}, "order_id": {"N": "4"}, "status": {"S": "new"}},
    {"customer": {"S": "tanaka"}, "order_id": {"N": "9"}, "status": {"S": "paid"}},
]

def scan(items):
    return {"Count": len(items), "ScannedCount": len(items)}

def query(items, customer):
    found = []
    for item in items:
        if item["customer"]["S"] == customer:
            found.append(item)
    return {"Count": len(found), "ScannedCount": len(found)}

print("スキャン:", scan(orders))
print("sato のクエリ:", query(orders, "sato"))
# "sato" を "suzuki" に変えましょう。クエリが見る項目は、いくつになりますか。

フィルターは答えを減らすが、仕事は減らさない

キー条件では、ソートキーも判定できます。たとえば、order_id が 2 以上、という形です。するとサービスは、パーティションのその部分だけを読みます。

フィルターは、status のような、ほかの属性を判定します。項目を読んだあとに働くので、Count は変わりますが、ScannedCount は変わりません。

例: sato の paid の注文、2番から

手順残る項目何が起きたか
パーティションキーが sato3注文 1、2、3
ソートキーが 2 以上2注文 2 と 3。ScannedCount は 2
フィルター: status が paid1注文 3 だけ。Count は 1

学生が入力するセルは、このプレビューでは空白です。

よくある間違い

注意

フィルターを使うと、読み取りが安くなる、と考える人が多いです。安くなりません。サービスは先に項目を読み、あとから一部を捨てます。できるだけキー条件に入れ、残りだけにフィルターを使います。

実行: 2つの数を読む

コード: python
answer = {
    "Count": 1,
    "ScannedCount": 2,
    "Items": [
        {"customer": {"S": "sato"}, "order_id": {"N": "3"}, "status": {"S": "paid"}},
    ],
}

dropped = answer["ScannedCount"] - answer["Count"]
print("見た数:", answer["ScannedCount"])
print("返した数:", answer["Count"])
print("フィルターが捨てた数:", dropped)
# ScannedCount を 3 に変えましょう。フィルターが捨てた数は、いくつになりますか。

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。