PostgreSQLの並行インデックス作成:AddIndexConcurrentlyと代替方法の比較


postgres.operations.AddIndexConcurrently は、Django の django.contrib.postgres モジュールが提供するマイグレーション操作クラスです。このクラスは、PostgreSQLデータベースにおいて、並行処理でインデックスを作成することを可能にします。

利点

従来の AddIndex 操作とは異なり、AddIndexConcurrently を使用することで、インデックス作成処理中にテーブルに対する書き込み操作をロックすることなく、アプリケーションのダウンタイムを最小限に抑えることができます。これは、大量のデータを持つアクティブなプロダクション環境において特に重要です。

使用方法

AddIndexConcurrently を使用する方法は、以下のとおりです。

from django.contrib.postgres.operations import AddIndexConcurrently

class Migration(migrations.Migration):

    operations = [
        AddIndexConcurrently(
            model_name='app_name.model_name',
            fields=['field_name1', 'field_name2'],
            name='my_index_name'
        ),
    ]

上記の例では、app_name アプリケーションの model_name モデルに対して、field_name1field_name2 フィールドに基づくインデックス my_index_name を作成します。

注意点

  • インデックス作成処理は、従来の AddIndex 操作よりも時間がかかる場合があります。
  • AddIndexConcurrently 操作は、PostgreSQL 9.1 以降のバージョンが必要です。

postgres.operations.AddIndexConcurrently は、PostgreSQLデータベースにおいて、パフォーマンスを犠牲にすることなく、ダウンタイムを最小限に抑えながらインデックスを作成するための強力なツールです。

  • Django 3.2 より前のバージョンで PostgreSQL の並行インデックス作成を使用するには、サードパーティ製のライブラリを使用する必要があります。
  • AddIndexConcurrently 操作は、Django 3.2 以降で使用できます。


from django.contrib.postgres.operations import AddIndexConcurrently

class Migration(migrations.Migration):

    operations = [
        AddIndexConcurrently(
            model_name='app_name.model_name',
            fields=['field_name'],
            name='my_index_name'
        ),
    ]

この例では、app_name アプリケーションの model_name モデルに対して、field_name フィールドに基づくインデックス my_index_name を作成します。

例2: 複数のフィールドに基づくインデックスの作成

from django.contrib.postgres.operations import AddIndexConcurrently

class Migration(migrations.Migration):

    operations = [
        AddIndexConcurrently(
            model_name='app_name.model_name',
            fields=['field_name1', 'field_name2'],
            name='my_index_name'
        ),
    ]

例3: 部分インデックスの作成

from django.contrib.postgres.operations import AddIndexConcurrently

class Migration(migrations.Migration):

    operations = [
        AddIndexConcurrently(
            model_name='app_name.model_name',
            fields=['field_name'],
            where={'field_name2__gt': 10},
            name='my_index_name'
        ),
    ]

この例では、app_name アプリケーションの model_name モデルに対して、field_name フィールドに基づくインデックス my_index_name を作成し、field_name2 フィールドの値が 10 を超えるレコードのみを対象とします。

例4: インデックスの種類を指定

from django.contrib.postgres.operations import AddIndexConcurrently

class Migration(migrations.Migration):

    operations = [
        AddIndexConcurrently(
            model_name='app_name.model_name',
            fields=['field_name'],
            name='my_index_name',
            using='btree'  # 'btree', 'gin', 'hash', など
        ),
    ]

例5: 既存のインデックスを削除

from django.contrib.postgres.operations import RemoveIndexConcurrently

class Migration(migrations.Migration):

    operations = [
        RemoveIndexConcurrently(
            model_name='app_name.model_name',
            name='my_index_name'
        ),
    ]

この例では、app_name アプリケーションの model_name モデルから my_index_name インデックスを削除します。

  • インデックス作成処理は、従来の AddIndex 操作よりも時間がかかる場合があります。
  • postgres.operations.AddIndexConcurrently 操作は、PostgreSQL 9.1 以降のバージョンが必要です。


postgres.operations.AddIndexConcurrently は、PostgreSQLデータベースにおいて、並行処理でインデックスを作成するための便利なツールです。しかし、すべての状況において最適な方法であるとは限りません。

代替方法

以下に、postgres.operations.AddIndexConcurrently の代替方法をいくつか紹介します。

AddIndex 操作を使用する

AddIndex 操作は、postgres.operations.AddIndexConcurrently と異なり、インデックス作成処理中にテーブルに対する書き込み操作をロックします。そのため、アプリケーションのダウンタイムが発生する可能性があります。しかし、AddIndexConcurrently よりも高速にインデックスを作成できる場合があり、シンプルなインデックス作成であれば十分な場合があります。

from django.db import migrations

class Migration(migrations.Migration):

    operations = [
        migrations.AddIndex(
            model_name='app_name.model_name',
            fields=['field_name'],
            name='my_index_name'
        ),
    ]

ALTER TABLE SQLステートメントを使用する

ALTER TABLE SQLステートメントを使用して、インデックスを直接作成することもできます。この方法は、より詳細な制御が必要な場合や、postgres.operations.AddIndexConcurrently でサポートされていないインデックス種類を作成する場合に役立ちます。

ALTER TABLE app_name_model_name ADD INDEX my_index_name (field_name);

データベースマイグレーションツールを使用する

Sequel Pro や DBeaver などのデータベースマイグレーションツールを使用して、インデックスを作成することもできます。これらのツールは、視覚的なインターフェースを提供し、複雑なインデックス作成タスクを簡素化することができます。

インデックス作成をスケジュールする

アプリケーションのダウンタイムを許容できる場合は、インデックス作成をオフピーク時間にスケジュールすることができます。これは、大量のデータを持つプロダクション環境において特に有効です。

インデックスが必要かどうかを再検討する

すべてのクエリにおいてインデックスが必要とは限りません。インデックスを作成する前に、クエリのパフォーマンスを分析し、実際にインデックスが必要かどうかを判断することが重要です。

選択の指針

どの代替方法を選択するかは、状況によって異なります。以下の点を考慮する必要があります。

  • 必要な制御レベル
  • 使用しているデータベースマイグレーションツール
  • インデックスの種類
  • インデックス作成に必要な時間
  • アプリケーションのダウンタイム許容時間

postgres.operations.AddIndexConcurrently は、PostgreSQLデータベースにおいて、並行処理でインデックスを作成するための便利なツールですが、すべての状況において最適な方法であるとは限りません。上記で紹介した代替方法も考慮し、状況に合った方法を選択することが重要です。

  • Django 4.0 以降では、AddIndexConcurrently 操作がデフォルトで並行処理を使用するように更新されています。