第21話 Database よくある勘違い
「TeradataはPrimary Indexが一意に近いほどパフォーマンスが上がる」
当社は様々なRDBを扱っております。
しかし各RDBには様々な特性があり、それらを考慮して扱わないと、本来持つパフォーマンスを発揮できないことがあります。現在私が主に扱っているRDBは「大量データを高速で処理すること」に特化したTeradataですが、今回このTeradataの特性について少し述べたいと思います。
Teradataのテーブルには、1つまたは複数の列からなる「Primary Index (以下PI)」と呼ばれるインデックスが定義されています。
TeradataはPI列の値に基づき、どのディスクにそのレコードを配置するかを決定します。PIの値が十分に分散していなければ(例えばYes/Noの2値しかなければ)、レコードは特定のディスク群に偏って配置され、読み書きのパフォーマンス低下や「Disk Fullエラー」の原因となります。よって、PIには偏りの少ない、多様な値を持つ列を指定することが強く推奨されます。
以上はTeradataを扱う際に最初に教わることですが、ここから
「PIが一意に近いほどパフォーマンスが上がる」
「データの偏りは極力0に近づけなくてはならない」
と誤解し、PI列を増やすことで一意に近づけようとする例が時おり見られます。
PI列の変更は、クエリのパフォーマンス低下の原因になるので慎重に行う必要があるのです。
あるシステムでは、数億件を保持する売上実績テーブルに対して「顧客番号」のみをPIに指定していました。
これではデータの配置に偏りが出るので、PIを「顧客番号」「商品コード」「受注日」の3列にして偏りを消すべきではないか、という指摘を他社の方から受けたことがありました。実際、顧客番号のみで配置されたデータには3.5%ほどの偏り(*注1)があり、ここでPIを{ 顧客番号, 商品コード, 受注日 }にすれば、偏りがほぼ0になることもわかりました。
(*注1)各ディスクに配置された行数の平均を100とすれば、最大の行数を格納するディスクには103.5件ある、という状態
しかし我々はPIの変更を行いませんでした。PIを複数列に変更すると、顧客番号を結合キーに使用するクエリが、多くの場合低速になるからです。PIの変更により、最速の結合方式である「RowHash match scanによるMerge Join」が使用できなくなり、代わりにより低速な「複数パーティションのHash Join」が採用されるため、パフォーマンスが大幅に低下するのです。
SQLのパフォーマンスチューニング作業においても、PIは最初に確認する項目の一つです。低速なクエリの中に、PIの選定が間違っているテーブルを発見できれば、そのPIを修正するだけで実行時間が三分の一、五分の一になることも珍しくありません。
PIはクエリの結合処理のパフォーマンスを決定する、最も重要な要因なのです。
PIと結合方式の関係はどのようなものか。
またPIは一般的なRDBのインデックスと何が違っているのか。
次回はその辺りのお話をさせていただこうと思います。
日付2012/11/01