データベース設計やSQLのパフォーマンスチューニングの文脈でよく耳にする「カーディナリティ(Cardinality)」という言葉。
日本語では「多重度」や「濃度」と訳されることがありますが、具体的に何を指し、なぜ重要なのか、少し曖昧なまま使っている方もいるかもしれません。
この記事では、エンジニアが知っておくべきカーディナリティの概念と、それがデータベースのパフォーマンスにどう影響するかを解説します。
カーディナリティとは?
一言で言うと、あるカラム(列)に含まれる値の種類の多さのことです。
値の種類が多ければ「カーディナリティが高い」、少なければ「カーディナリティが低い」と表現します。
具体例でイメージする
例えば、users(ユーザー)テーブルを想像してみてください。
1. カーディナリティが高い例:IDやメールアドレス
user_id や email カラムはどうでしょうか?
これらはユーザーごとに異なる一意(ユニーク)な値が入ります。
100万人のユーザーがいれば、100万通りの値が存在することになります。
このように、行数に対してユニークな値の比率が高いカラムは、カーディナリティが高いと言えます。
2. カーディナリティが低い例:性別やフラグ
一方で、gender(性別)や is_active(有効フラグ)カラムはどうでしょうか?
性別なら「男性」「女性」「その他」の数種類、フラグなら「0(無効)」「1(有効)」の2種類しか値がありません。
たとえユーザーが100万人いても、値の種類はほんの数種類です。
このようなカラムは、カーディナリティが低いと言えます。
なぜカーディナリティが重要なのか?
カーディナリティの概念が特に重要になるのは、インデックス(Index)の設計とクエリのパフォーマンスを考える時です。
インデックスの効きやすさ
一般的に、カーディナリティが高いカラムほど、B-Treeインデックスの効果が高くなります。
インデックスは、辞書の索引のようなものです。
例えば、「IDが 12345 のユーザーを探したい」という場合、IDはカーディナリティが高く、特定の一行にピンポイントで絞り込めるため、インデックスを使えば爆速で検索できます。
逆に、カーディナリティが低いカラム(例えば「性別」)にインデックスを貼っても、あまり効果が得られないことがあります。
「男性」で検索しても、全体の約半数がヒットしてしまうような場合、データベースは「インデックスを使ってちまちま探すより、最初から全部読み込んだ方(フルスキャン)が速い」と判断することがあるからです。
クエリオプティマイザへの影響
データベースのクエリオプティマイザ(実行計画を決める機能)は、統計情報として各カラムのカーディナリティを保持しています。
「この条件で絞り込むと、大体これくらいの行数になりそうだ」という予測(見積もり)を立てる際に、カーディナリティが重要な判断材料になります。
データベース設計におけるカーディナリティ
データモデリング(ER図などを書く時)におけるカーディナリティは、テーブル間の**リレーションシップ(関係性)**におけるレコードの対応数を指します。
こちらも「1対1」「1対多」などの言葉で表現されます。
-
1対1 (One-to-One):
- 例:ユーザーとユーザー詳細情報。1人のユーザーに対して、詳細は1つだけ。
-
1対多 (One-to-Many):
- 例:ユーザーと注文履歴。1人のユーザーは何度も注文できるが、ある注文は特定の1人のユーザーのもの。
-
多対多 (Many-to-Many):
- 例:学生と授業。1人の学生は複数の授業を受け、1つの授業には複数の学生がいる。中間テーブルを用いて表現するのが一般的。
まとめ
- カーディナリティとは、カラムに含まれる値の種類の多さのこと。
- カーディナリティが高い(IDなど)= インデックスが効きやすい。
- カーディナリティが低い(性別など)= インデックス効果が薄い場合がある。
- データベースのパフォーマンスを考える上で、どのカラムのカーディナリティが高いかを意識することは非常に重要。
「このカラムにインデックスを貼るべきか?」と迷ったときは、まずそのカラムのカーディナリティを確認してみましょう!