Aikido

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

パフォーマンス

ルール

避ける 冗長な データベース インデックス。
重複する データベース インデックス 無駄にする
ストレージ そして 遅くする  書き込み。

対応言語: SQL

はじめに

不要なインデックスは、複数のインデックスが同じ列をカバーしている場合、またはあるインデックスが別のインデックスのプレフィックスである場合に発生します。すべてのインデックスはディスク領域を消費し、INSERT、UPDATE、DELETE操作時に更新される必要があります。類似の列に5つの重複するインデックスを持つテーブルは、読み取り最適化には1つのインデックスで十分であるにもかかわらず、書き込みパフォーマンスのペナルティを5回支払うことになります。

なぜ重要なのか

パフォーマンスへの影響: データが変更されるとデータベースがすべてのインデックスを更新する必要があるため、すべてのインデックスは書き込み操作を遅くします。冗長なインデックスは、クエリのメリットを提供することなくこのコストを増大させます。3つの冗長なインデックスを持つテーブルは user_id 常に1つのインデックスしか使用されないにもかかわらず、書き込みオーバーヘッドを3倍にします。

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

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

コード例

❌ 非準拠:

-- usersテーブル上の冗長なインデックス
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_email_status ON users(email, status);
CREATE INDEX idx_users_created ON users(created_at);
CREATE INDEX idx_users_created_status ON users(created_at, status);

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

誤っている理由: メール上のインデックスは冗長です。なぜなら idx_users_email_status ~で始まる メール そしてメールアドレスのみでフィルタリングするクエリを処理できます。同様に、 idx_users_created と重複しています idx_users_created_status。このテーブルへの挿入または更新ごとに、2つで十分なところを4つのインデックスが更新されます。

✅ 準拠済み:

-- usersテーブル上の最適化されたインデックス
CREATE INDEX idx_users_email_status ON users(email, status);
CREATE INDEX idx_users_created_status ON users(created_at, status);

-- 複合インデックスは、そのプレフィックス列に対するクエリに対応できます
-- emailのみのクエリはidx_users_email_statusを使用します
-- created_atのみのクエリはidx_users_created_statusを使用します

これが重要である理由: 2つの複合インデックスがすべてのクエリパターンに対応し、冗長性を排除します。~でフィルタリングするクエリ メール 単独で最初のインデックスを使用し、クエリは以下でフィルタリングされます。 created_at 単独で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つの中央システムでセキュアに。
脆弱性を迅速に発見し、自動的に修正。

クレジットカードは不要です | スキャン結果は32秒で表示されます。