理系学生日記

おまえはいつまで学生気分なのか

逆キー索引についてのまとめ

時刻をキーとしているログテーブルを insert するロジックを組んでいるケースで、このログテーブルにバースト的な insert が走ると、パフォーマンスが悪化するという事象が散見されました。
調査した結果、インデックス競合によって後段の insert が待ちになっているようです。

一般的に、DB のインデックスは B*Tree のデータ構造を取りますが、インデックスを構成するカラムに昇順の値がバースト的に insert されるケースでは、この B*Tree の最後のリーフに対する処理が集中し、I/O 的なボトルネックが発生します。これを防ぐための一般的な解決策としては、キー値データを逆順に並べて格納する「逆キー索引」を使うことが挙げられます。

「逆キー索引」とは、B*Tree 上のキーを byte レベルで逆順に並べる索引で、値自体が昇順で insert されても、特定のリーフブロックに処理が集中することがなくなります。これにより、上記のような問題を解決することができます。
ただし、当然ながらデメリットもあり、辞書順で連続する値を持つレコードであっても、そのレコードが格納されるディスク上の領域は隣接しないようになります。従って、逆キー索引では範囲検索が使えません。

というわけで、バースト的な insert でパフォーマンス劣化が発生した場合、索引を構成するカラムに対する範囲検索が使われていないことを確認し、それがないようであれば逆キー索引を使うという選択肢を考えることになります。

参考