🎉

イラストで理解するDynamoDBのカーディナリティ

2023/06/08に公開

はじめに

「カーディナリティ」みなさん聞いたことありますか?
私の場合はAWSのDVAの勉強をしていた際に突然現れ、初めて目にしました。

この厨二病を拗らせたような名前の「カーディナリティ」、実はDynamoDBの設計において大切な概念でした。
今回はそんな「カーディナリティ」について調べてみました。

カーディナリティって?

まず、一応wiki的な説明をすると
カーディナリティは特定の属性(カラム)が持つ値のバリエーションです。

使い方としては、カーディナリティが高いとか低いって言います。

私はこの説明で????ってなりました。
そこで、以前書いたDynamoDBの概要記事をベースに考えていきます。
https://qiita.com/Yona_Sou/items/caf1d2ac5867ed0c3154

特定の属性のバリエーションとは?

まずはテーブルの全体像を見てみましょう。
"学校"というテーブルに
"クラス"というパーティションがあります。
その中に生徒の情報という属性があります。

図にするとこんな感じです。

では、この中から一人の生徒を見てみましょう。

注目するのはこの「属性」の「値(value)」です。

値というのは、この図でいうところの「山田太郎」です。
「名前」という属性に入る値はいくつあるでしょう?
それは人の数だけありますね。
「鈴木花子」も「佐藤一郎」も「田中ゆうこ」も値です。

この値がたくさんある、ということは属性のバリエーションが多いということです。
これはカーディナリティが高いということです。

では逆に、「性別」という属性はどうでしょうか?
ここでは「男」か「女」です。
バリエーションは2つです。

こちらはバリエーションが少ないですね。
ということはカーディナリティが低いと言えます。

これでなんとなくカーディナリティという言葉の意味は理解できたでしょうか。

「カーディナリティ」が高いと何がいいの?

データベースの設計においてカーディナリティは高い方が良いとされています。
ではなぜ高い方が良いのか考えていきましょう。

今回は条件として1クラス35人の8クラスで男女比が1:1とします。

クラスがパーティションキーの場合

先ほどの"学校"テーブルのクラスを軸にクエリをかけます。
では1組の生徒を一覧で呼び出してみます。

$ aws dynamodb query \
    --table-name School \
    --index-name ClassroomIndex \
    --key-condition-expression "Classroom = :classroom_val" \
    --expression-attribute-values '{":classroom_val":{"S":"1組"}}'
{
    "Items": [
        {
            "Gender": {
                "S": "Male"
            },
            "Classroom": {
                "S": "1組"
            },
            "StudentName": {
                "M": {
                    "FirstName": {
                        "S": "太郎"
                    },
                    "LastName": {
                        "S": "山田"
                    }
                }
            },
            "StudentNumber": {
                "N": "1"
            },
            "FavoriteColor": {
                "S": "red"
            },
            "Subject": {
                "S": "理科"
            }
        },
        {
            "Gender": {
                "S": "Female"
            },
            "Classroom": {
                "S": "1組"
            },
            "StudentName": {
                "M": {
                    "FirstName": {
                        "S": "花子"
                    },
                    "LastName": {
                        "S": "鈴木"
          ...

このようにそのクラスの人が一覧で取得できます。
1クラスの35人分の生徒の情報が呼び出されます。

性別がパーティションキーの場合

では次に、「性別」を軸に
「男」という値で生徒を呼び出してみます。

$ aws dynamodb query \
    --table-name School \
    --index-name GenderIndex \
    --key-condition-expression "Gender = :gender_val" \
    --expression-attribute-values '{":gender_val":{"S":"Male"}}'
{
    "Items": [
        {
            "Gender": {
                "S": "Male"
            },
            "Classroom": {
                "S": "1組"
            },
            "StudentName": {
                "M": {
                    "FirstName": {
                        "S": "太郎"
                    },
                    "LastName": {
                        "S": "山田"
                    }
                }
            },
            "StudentNumber": {
                "N": "1"
            },
            "FavoriteColor": {
                "S": "red"
            },
            "Subject": {
                "S": "理科"
            }
        },
        {
            "Gender": {
                "S": "Male"
            },
            "Classroom": {
                "S": "1組"
            },
            "StudentName": {
                "M": {
                    "FirstName": {
                        "S": "一郎"
                    },
                    "LastName": {
                        "S": "佐藤"
          ...

こちらは、全クラスの男子が呼び出されました。
合計で280人分です。

ここで大事なのは
一回の検索で何人の情報が呼び出されたか?です。

あなたは学校の先生だとして、 「35人の生徒を集める」のと、「280人の生徒を集める」のは
どちらが簡単だと思いますか?

圧倒的に前者ですね。
ここでの「集める」は「データを呼び出す」と言い換えられます。

つまり?

上の例では
「クラス」という括り(パーティションキー)で呼び出すと35人でした。
「性別」という括り(パーティションキー)で呼び出すと280人でした。

これから言えることは
パーティションキー自体のバリエーションが多いほどデータが分散されるということです。
データが分散すると、パーティション毎のデータ量が減ってデータの呼び出しが楽になるということです。

これは、「クラス」が「性別」に比べてバリエーションが多いからです。
それはつまりカーディナリティが高いということです。

まとめ

いかがでしたでしょうか。
最初は訳のわからない横文字が出てきてびっくりしましたが、よくよく調べるとDB設計においてとても大切なことでした。

GitHubで編集を提案

Discussion