カーディナリティが高いと、ストレージの効率は低下しますが、読み取りパフォーマンスは向上します。これは、クエリの行を絞り込むために、探しているデータに到達するために、より少ないブランチをナビゲートする必要があるためです。
定義上、読み取るレコードが少ないため、カーディナリティが高いほど、読み取りパフォーマンスが向上します。
このようなクエリを処理するには:
SELECT *
FROM mytable
WHERE indexed_col = @myvalue
、エンジンは次の手順を実行する必要があります。
条件を満たす最初のエントリを見つけます。
これはB-Tree
、ルートエントリから開始して、をトラバースして実行されます。
ページ全体で、検索は次のB-Tree
リンクによって実行されます。ページ内では、検索はバイナリ検索を使用して実行されます(キーが圧縮されている場合を除きます。圧縮されている場合は、線形検索です)。
このアルゴリズムは、カーディナリティの高い列とカーディナリティの低い列の両方で同じ効率です。これらのリストで3
(いずれかではなく)最初のものを見つける:3
1 2 3 4 5 6 7 8 9 10
3 3 3 3 3 3 3 3 4 4
同じO(log(n))
手順が必要です。
キー値が変更されるまでインデックスをトラバースします。もちろん、これには線形時間が必要です。レコードが多いほど、トラバースする必要があります。
最初のレコードのみが必要な場合:
SELECT *
FROM mytable
WHERE indexed_col = @myvalue
LIMIT 1
、列のカーディナリティは読み取りパフォーマンスに影響しません。
カーディナリティは書き込みパフォーマンスにどのように影響しますか?
各インデックスキーには、レコードポインタという隠された追加の値があります。これがインデックスを持つことの全体的なポイントです。どのレコードを指しているのかを知る必要があります。
レコードポインタは定義上一意であるため、各インデックスキーも一意です。同じキー値を共有するインデックスエントリは、レコードポインタによって並べ替えられます。
これは、インデックスを保守しやすくするためです。他の何百万ものレコードと共有されているインデックス付き列の値を持つレコードを削除する場合は、対応するインデックスレコードも削除する必要があります。しかし、100万のインデックスレコード全体が調べられていません。代わりに、レコードポインタが追加の検索条件として使用されます。
各インデックスキーは実際には一意であり(インデックスを一意として定義していなくても)、したがって、可能な限り最大のカーディナリティを持ちます。
したがって、質問に対する答えは次のとおりです。いいえ、列のカーディナリティはインデックスの書き込みパフォーマンスに影響しません。