プライマリ・インデックスって？

こんにちは！

今日はVantageのテーブル作成における唯一といってもいい顧慮ポイント、プライマリ・インデックスについてお話したいと思います。
このプライマリ・インデックス、Vantageでしか聞かないものですのでどうしても身構えがちですが、実はこれも複雑なものではありません。そのポイントについて紹介します。

# プライマリ・インデックスでデータを分散する
[Vantageのソフトウェア・アーキテクチャ](https://qiita.com/ykswi/items/ed25a13eaf0f85a5103a)で触れましたが、プライマリ・インデックスはVantageの各並列プロセッサにテーブルのレコードを分散するために使用される項目です。Vantageは各レコードのプライマリ・インデックス項目の値を元にハッシュ値を算出し、そのハッシュ値によってデータをその並列プロセッサに割り当てるのかを決めるということは前出の記事の中で紹介しました。
それではプライマリ・インデックス項目としてどんな項目を選べばいいのでしょう？

# ユニークか？ユニークにしないか？
Vanatgeを初めて利用されるお客様でよく誤解されるのが、
　　「できるだけ均等にデータを分散した方が効率が良くなるだろう」
ということです。

そう考えるとプライマリ・インデックスを作成する際にテーブルの各レコードをユニークに識別するための項目すべてを使ってプライマリ・インデックスを構成しがちです。リレーショナル・データベースにお詳しい読者の皆さんにはもうお分かりかと思いますが、プライマリ・インデックス項目=プライマリ・キー項目とするということになります。そうした方がテーブルを作成する際に考えることが減らせますし。

たしかにより均等に分散されたデータを処理する場合には並列性は高まります。すべての並列プロセッサが同じ量の仕事をすることになるためです。一つのテーブルから単純にレコードを検索するような処理を行う場合にはこの方法がもっともクエリー・パフォーマンスを向上できます。ところがリレーショナル・データベースではこのように単純なデータの検索を行うということは極めて稀ともいえる処理パターンで、通常は複数のテーブルを結合して検索することになります。この「複数のテーブルを結合」というのがユニーク性を求めるあまりプライマリ・インデックスを構成する項目の数を多くしすぎたテーブルのパフォーマンス上の弱点となります。

それはこんな理由によります。

##### テーブル結合を行うリレーショナル項目はプライマリ・キー項目と完全一致することはほぼない

これはみなさんも経験上よくご存じでしょう。結合で使用されるリレーショナル項目はマスターとの結合のための属性コードや各データの検索対象を絞り込むための項目（顧客や取引などに割り当てられたID）であることがほとんどです。

##### Vantageの並列プロセッサは自身が持っているレコード以外処理することはできない
これは「そういうもの」と考えていただければいいのですが、トランプゲームの際に他人が持っているカードを自分の手札として使うことができないのと同じことです。

これらの制約を乗り越え結合を行うためVantageは各並列プロセッサが持っているデータの交換やコピーを行って結合に必要なデータがきちんと各並列プロセッサに揃っている状態を作りながらクエリーを処理します。
ここで考えてみてください。結合する2つのテーブルが同じ項目をプライマリ・インデックスを持っていたとしたら。このデータの交換やコピーは不必要になりその分処理時間は短くできるのです。

そのためプライマリ・インデックスを無理に（たくさんの項目を使って）ユニークにするのではなく、多少分散にばらつきがあってもユニークでないプライマリ・インデックスを作る方がパフォーマンスを向上できます。

# プライマリ・「インデックス」
これも先の記事で触れましたがプライマリ・インデックスにはなぜ「インデックス」という言葉がついているのかということです。プライマリ・インデックスは検索時のインデックスとしても使用されます。Vantageはプライマリ・インデックス項目についてどの値の場合どこにそのデータがあるということを認識しています。そのためクエリーの条件にプライマリ・インデックス項目のすべてが含まれていると非常に高速に検索を行うことができます。

# データ分散の考慮
だからと言ってVantageの並列性を保つためにはデータの分散を全く考慮に入れなくてよいということにはなりません。20の並列プロセッサを持つシステムで10のユニーク・バリューしかない項目をプライマリ・インデックスとして選ぶのはシステムの効率上よいことにはなりません。
ただ、もちろんレコード数が並列プロセッサの数より小さかったり、各並列プロセッサのレコード数がせいぜい数行というような極めて小さなテーブルでは気にすることではありません。気にしたとしても実際に各並列プロセッサにデータ分散することは不可能なわけですし。

またユニークバリューごとのレコード数のことも考えてください。例えば日本人をレコードとしたテーブルを作ったとして、プライマリ・インデックスを都道府県コードとした場合には人口の最も多い東京都と最も少ない県のレコード数の差は数十倍になってしまいます。

# プライマリ・インデックスにどの項目を選ぶのか？
これまでにお話したことを鑑みてプライマリ・インデックス項目を選択すると
・ 結合条件や検索条件によく使われるであろう項目を選ぶ
・ 項目のユニーク・バリュー数の差がそれほど大きくないものを選ぶ

テーブルのデータを見てみればそのような項目はおのずと見えてくるものです。

# ユニーク・プライマリ・インデックスの使いどころ
Vantageのプライマリ・インデックスをユニークにする（Unique Primary Indexとして定義する）とそれはそれでよいこともあります。

Vantageにはテーブルの種類としてSETテーブルとMULTI SETテーブルがあります。何が違うかというとSETテーブルは「各項目の値がすべて同じ値のレコードは複数存在できない」という制約がつきます。SETテーブルでは特に億レベルのレコード件数になるとこのチェックに結構な時間を要します。
ところがユニーク・プライマリ・インデックスを持つテーブルの場合にはこのインデックス部分のみをチェックするだけでよくなり、このチェックに時間をかけなくてもよくなるのです。

逆に言うとプライマリ・インデックスをユニークにしなかった場合はMULTI SETテーブルとして、完全一致する行の存在を許すか、他の方法（プライマリ・キー項目でユニーク・セカンダリ・インデックスを作成する）でチェックにかかる負荷を軽減してください。

# より詳しく知るには
・ [Teradata Vantage™ - SQLデータ定義言語 詳細トピック](https://docs.teradata.com/r/7IqmsKx4YhvVMZd6Ca~pPw/XCPuUFbfHKUoJBuwqMF9Ww)
・ [Teradata Vantage™ - Database Design（英語）](https://docs.teradata.com/r/Teradata-VantageTM-Database-Design-17.20)

#### Teradata Vantageへのお問合せ
[Teradata Vantage へのお問合せ](https://www.teradata.jp/About-Us/Contact)