はじめに
最近、速度改善を行う機会が度々あり、クエリチューニングによる速度改善について検討・調査していました。その中でカバリングインデックスが高速であると知り、カバリングインデックスの利用による速度改善について調べました。
カバリングインデックスとは
カバリングインデックス(Covering Index 以降、CI)とは、検索条件に使用するカラムだけでなく、SELECTで取得するカラムもインデックス内に含めることで、テーブル本体へのアクセスを不要にする仕組みです。
例えば、以下のようなテーブルがあるとします。
employees
----------------
id
shop_id
position_id
is_working通常のインデックス:
CREATE INDEX idx_shop_position
ON employees(shop_id, position_id);この状態で、
SELECT is_working
FROM employees
WHERE shop_id = 1
AND positon_id = 3;を実行すると、インデックスで対象データを見つけた後、テーブル本体からis_workingを取得します。
一方で、
CREATE INDEX idx_shop_position_working
ON employees(shop_id, position_id, is_wornking);のようにis_workingもインデックスに含めると、インデックスだけで必要な情報を取得できるため、テーブルへのアクセスを省略できます。
EXPLAINを実行した際に「Using index」と表示される場合、CIが利用されている可能性があります。
メリット
1. 検索速度の向上
基本的に速度改善目的で使用するものなので速度が上がります。
2. DB負荷を軽減できる
テーブル本体のアクセスが不要になるので負荷軽減も見込めます。
デメリット
1. INSERT / UPDATE / DELETE が遅くなる
インデックス全般に言える事ですが、データ変更時にはインデックスも更新されるため、不用意に張りすぎると INSERT / UPDATE / DELETE が遅くなります。
2. メンテナンスコストが増える
実際にCIを使おうと思うとこれが大きなデメリットだと感じました。
既にCIを張っているクエリがあったとして、そのクエリでの取得カラムを増やすと、CIを張り直す必要が出てきます。毎回忘れずに管理できるとも限らないし、テーブルが大きかったり、アクセス頻度が高いテーブルであれば都度インデックスを張り直すのが難しい場面もあると思います。
元々、CIが効いていて高速だったが、取得カラムを増やした結果CIが効かなくなり速度が落ち、今すぐCIを張り直すのも難しい状況とかになると苦しいです。
さいごに
結論、CIに依存して速度改善を行う事はあまり現実的ではないと感じました。ただ、自分が速度改善目的で張ったインデックスはCIであるために高速になったのではないか、今後CIが効かなくなり速度が低下する懸念がないかという視点は常に持っておきたいです。速度改善においてインデックスは不可欠だと思うので、引き続き理解を深めていきたいです。