イラストで理解するDynamoDBのカーディナリティ
はじめに
「カーディナリティ」みなさん聞いたことありますか?
私の場合はAWSのDVAの勉強をしていた際に突然現れ、初めて目にしました。
この厨二病を拗らせたような名前の「カーディナリティ」、実はDynamoDBの設計において大切な概念でした。
今回はそんな「カーディナリティ」について調べてみました。
カーディナリティって?
まず、一応wiki的な説明をすると
カーディナリティは特定の属性(カラム)が持つ値のバリエーションです。
使い方としては、カーディナリティが高いとか低いって言います。
私はこの説明で????ってなりました。
そこで、以前書いたDynamoDBの概要記事をベースに考えていきます。
特定の属性のバリエーションとは?
まずはテーブルの全体像を見てみましょう。
"学校"というテーブルに
"クラス"というパーティションがあります。
その中に生徒の情報という属性があります。
図にするとこんな感じです。
では、この中から一人の生徒を見てみましょう。
注目するのはこの「属性」の「値(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設計においてとても大切なことでした。
Discussion