本稿では、私が普段の現場業務で使用しているデータベースから、 索引(インデックス)作成時に心得ておきたい事項を記載しています。
学科やプログラミングを独習するだけでは、なかなか知識として得られない、かつ私自身にも役立てている内容を紹介させて頂ければと思います。
本稿では、Oracle Database 11g Release 2 を対象としています。
データベースにおいて、実務上よくパフォーマンス劣化に陥りやすいのが、索引スキャンであることが多い気がします。
索引とは?という方は、下記のページを参考にしてみてください。
そんなパフォーマンス劣化を防ぐためにも、索引作成時に主な次の3点を考慮すると、索引が有効に働き、パフォーマンスの向上につながります。
表にある程度のレコード件数が格納されていなければ、表フルスキャンの方が早いです。ある程度の目安としては、10,000 件程を指しています。
WHERE 句で指定されない列に対して索引を作成しても効果はありません。ただし、一意制約や主キー制約のための一意索引はこの限りではないです。
WHERE 句で指定される列であっても、その絞り込み条件により返されるレコード数の割合が大きいと、索引アクセスによる読み込みデータ量の低減効果は望めません。場合によっては、複数のデータ量をまとめて読み込むことのできる表フルスキャンの方が SQL の処理時間が短くなることもあります。
目安として、WHERE 句に指定される絞り込み条件により全体レコードの 10%以下が返される列に索引を付与することで、索引によるパフォーマンスの向上が図れます。
以上、3つの条件を考慮し、索引作成することを普段心がけています。
次のような会員表に対する SQL が実行されるとき、前述した3つの条件を考慮したうえで、どの列に索引を付けるべきでしょうか?
select 名前, プラン
from 会員表
where 名前 = '東京 花子'
and プラン = 'スタンダード'
まず、条件①「ある程度のレコード件数が格納されている表であること」を考えます。図にある説明では「総レコード数は、100,000 件」とあることから、十分なレコード数が格納されていることが分かるため、会員表に対して索引を作成する余地があると判断できます。
次に条件②「WHERE 句で指定されることが多い列である」を考えます。SQL の WHERE 句で指定されている列は [名前] 列と [プラン] 列の 2 列です。索引を付けるべき列の候補として、この 2 列が考えられます。
最後に条件③「WHERE 句に指定される絞り込み条件により全体レコードの 10% 以下が返される列である」を考えます。参照している会員表の総レコード数が 100,000 件なのに対し、 [名前] 列には 90,000 種類、 [プラン] 列には 2 種類のデータが含まれているとあります。
仮に次の SQL を実行した場合、
select 名前, プラン
from 会員表
where 名前 = '東京 花子'
90,000 種類から残りの 10,000 件全ての名前が「東京 花子」だとしても、返されるレコード数の割合は、総件数の 10% 以下です。
では、[プラン] 列のみで絞った場合を考えた場合、
select 名前, プラン
from 会員表
where プラン = 'スタンダード'
余程の偏り( 「スタンダード」プランの会員のみしかいない場合とか )がない限りは、10% 以下に絞られることはないでしょう。
したがって、すべての条件をクリアした [名前] 列に索引を付与することが望まれます。
いかがでしたでしょうか。
上記のように必ずしもそれに従っていれば最適であるというわけではありませんが、索引作成時の基礎的な考えを紹介させて頂きました。
なかなか、パフォーマンス性能をチェックすることは実務に携わってから学ぶことが多いのが現状かと思うのですが、逆を言えば実務に携わる前に知れる機会があれば、もっと根本的な処理や機械的な動作の仕組みから知れることになるため、強力な自分の武器となると言えるのではないでしょうか。
私自身もコード設計や開発していた頃は、見よう見真似で SQL を書いていましたが、データベースをメインに業務していると、かなり奥が深い世界だということを痛感しております。
開発するうえで、何かの一助になれば幸いです。