Aikido

冗長なデータベース・インデックスを避ける理由:ストレージと書き込みパフォーマンスの最適化

パフォーマンス

ルール

避ける 冗長な データベース インデックスの重複を避ける。
重複する データベース インデックス 無駄
ストレージ  スローダウン を削減する。 を書き込みます。

対応言語 SQL

はじめに

冗長インデックスは、複数のインデックスが同じカラムをカバーしている場合や、あるインデックスが他のインデックスのプレフィックスになっている場合に発生します。すべてのインデックスはディスクスペースを消費し、INSERT、UPDATE、DELETE操作で更新されなければならない。同じようなカラムに5つの重複したインデックスを持つテーブルは、読み取り最適化のためには1つのインデックスで十分なのに対して、書き込み性能のペナルティを5回支払うことになります。

なぜそれが重要なのか

パフォーマンスへの影響: データが変更されるとデータベースはすべてのインデックスを更新しなければならないため、すべてのインデックスが書き込み操作を遅くします。冗長インデックスは、クエリの利点を提供することなく、このコストを増加させます。に対する3つの冗長インデックスを持つテーブルは ユーザーID インデックスが1つしか使われないのに、書き込みのオーバーヘッドは3倍になる。

ストレージコスト:インデックスは、インデックスされた列のサイズと行数に比例してディスクスペースを消費する。冗長なインデックスは、実際のデータや有用なインデックスに使用できるはずのストレージを浪費する。不要なインデックスを持つ大きなテーブルは、ギガバイト単位のストレージを浪費する可能性がある。

メンテナンスの複雑さ:インデックスが増えるということは、監視、分析、保守する対象が増えるということです。データベース管理者は、価値のないインデックスの最適化に時間を費やします。クエリプランナーが評価する選択肢が増え、最適でない実行計画を選択する可能性がある。

コード例

非準拠:

-- usersテーブルの冗長インデックス
CREATEINDEX idx_users_email ONusers(email);
CREATEINDEX idx_users_email_status ONusers(email,status)に
CREATEINDEX idx_users_created ONusers(created_at)に作成された;
CREATEINDEX idx_users_created_status ONusers(created_at,status)に

-- 単一列インデックスは冗長である。
-- 複合インデックスが同じクエリに対応できるからです。

なぜそれが間違っているのか: 電子メールのインデックスは冗長である。 idx_users_email_status で始まる。 電子メール また、電子メールのみでフィルタリングされたクエリーを処理することができる。同様に idx_users_created とは冗長である。 idx_users_created_status.このテーブルへの挿入や更新はすべて、2つで十分なところを4つのインデックスを更新する。

✅ 準拠:

-- usersテーブルのインデックスの最適化
インデックスINDEX idx_users_email_status ONusers(email,status)にインデックスを作成します;
CREATEINDEX idx_users_created_status ONusers(created_at,status)に

-- 複合インデックスは、そのプレフィックス・カラムに対するクエリを提供することができます。
-- email だけに対するクエリは idx_users_email_status を使用します。
-- created_at だけに対するクエリは idx_users_created_status を使用する。

なぜこれが重要なのか: 2つの複合インデックスは、冗長性を排除しながら、すべてのクエリーパターンに対応する。によるフィルタリング 電子メール でフィルタリングするクエリは、最初のインデックスを使用する。 作成日時 を単独で使用する。4つのインデックスの代わりに2つのインデックスだけが更新を必要とするため、書き込みパフォーマンスは向上する。

結論

データベースのインデックスを定期的に監査し、冗長なインデックスを特定する。他のインデックスの接頭辞であったり、カバレッジが重複しているインデックスを削除する。複合インデックスは、その先頭カラムに対するクエリに対応することができるため、ほとんどの場合、個別の単一カラムインデックスを作成する必要がなくなります。

よくある質問

ご質問は?

データベースの冗長なインデックスを特定するには?

データベースのシステム・テーブルに問い合わせ、すべてのインデックスをリストする。PostgreSQLの場合はpg_indexesビューを使用してください。MySQLの場合はSHOW INDEX FROM table_nameを使用してください。インデックスが他のインデックスの接頭辞になっていたり(email対email+status)、複数のインデックスが同じカラムを異なる順序でカバーしているようなインデックスを探します。

単一列インデックスが複合インデックスと冗長でないのはどのような場合か?

クエリの選択性が重要な場合複合インデックスの2列目のみを頻繁にクエリする場合、そのクエリはインデックスを効率的に使用できません。(status, email)のインデックスは、emailのみでフィルタリングするクエリには役立ちません。しかし、(email, status)のインデックスはemailだけのクエリに対応できます。

冗長インデックスはクエリーパフォーマンスにどのような影響を与えるのか?

読み出しの場合は最低限、書き込みの場合はかなり。問い合わせプランナは冗長なインデックスを選択するかもしれませんが、実行時間は同様です。しかし、全ての書き込み(INSERT、UPDATE、DELETE)は全てのインデックスを更新する必要があり、I/O操作が増加します。書き込みの多いテーブルでは、冗長インデックスを削除することでスループットを20~50%向上させることができます。

複合インデックスがある場合、すべての単一列インデックスを削除すべきでしょうか?

必ずしもそうではない。単一列インデックスが非常に選択的で、単独で頻繁にクエリされるのであれば、そのままにしておきましょう。データベースのクエリ統計を使用して、どのインデックスが実際に使用されているかを確認する。使用率がゼロまたは非常に低いインデックスは削除する。最近のデータベースは、システムビューでインデックスの使用状況を追跡します。

まずは無料で体験

コード、クラウド、ランタイムを1つの中央システムでセキュアに。
脆弱性を迅速に発見し、自動的に修正。

クレジットカードは不要。