데이터베이스 인덱스 추가

인덱스는 데이터베이스 쿼리의 속도를 향상시키는 데 사용될 수 있지만, 언제 새 인덱스를 추가해야 할까요? 이 질문에 대한 전통적인 대답은 데이터 필터링이나 데이터 조인에 사용되는 모든 열에 대해 인덱스를 추가해야 한다는 것이었습니다. 예를 들어, 다음 쿼리를 고려해 보십시오.

SELECT *
FROM projects
WHERE user_id = 2;

여기서 user_id 열을 기준으로 필터링하고 있으므로, 개발자는 이 열에 대해 인덱스를 만들기로 결정할 수 있습니다.

특정 경우에는 위의 방법으로 열에 대한 인덱싱을 하는 것이 유용할 수 있지만, 실제로는 부정적인 영향을 미칠 수도 있습니다. 테이블에 데이터를 작성할 때 해당 테이블의 기존 인덱스도 업데이트해야 합니다. 인덱스가 많을수록 이 작업이 느려질 수 있습니다. 또한, 데이터가 색인화된 양과 색인 유형에 따라 디스크 공간을 상당히 차지할 수 있습니다. 예를 들어, PostgreSQL은 일반적인 B-tree 인덱스로 색인화할 수 없는 특정 데이터 유형을 색인화하는 데 사용할 수 있는 GIN 인덱스를 제공합니다. 그러나 이러한 인덱스는 일반적으로 더 많은 데이터를 차지하고 B-tree 인덱스에 비해 업데이트가 느립니다.

이 모든 이유로, 새로운 인덱스를 추가할 때 다음을 고려하는 것이 중요합니다.

  1. 새로운 쿼리가 가능한 한 많은 기존 인덱스를 재사용하는지 여부
  2. 색인을 사용하는 것이 테이블의 행을 반복하는 것보다 빠른지 여부
  3. 색인을 유지하는 데 드는 오버헤드가 쿼리 시간 단축에 알맞은 가치가 있는지 여부

일부 상황에서는 인덱스가 필요하지 않을 수도 있습니다.

  • 테이블이 작고(레코드가 1,000개 미만) 크기가 지수적으로 증가하지 않을 것으로 예상될 때
  • 기존 인덱스가 충분한 행을 필터링하는 경우
  • 색인이 추가된 후 쿼리 시간이 크게 감소하지 않을 경우

또한, 넓은 인덱스는 쿼리의 모든 필터 조건과 일치할 필요가 없습니다. 인덱스 조회의 선택성이 충분히 작아지도록 충분한 열을 커버하기만 하면 됩니다.

쿼리 재사용

첫 번째 단계는 쿼리가 가능한 한 많은 기존 인덱스를 재사용하도록 하는 것입니다. 예를 들어, 다음 쿼리를 고려해 보세요.

SELECT *
FROM todos
WHERE user_id = 123
AND state = 'open';

이제 user_id 열에 이미 인덱스가 있지만 state 열에는 인덱스가 없는 상황을 상상해 보십시오. state가 색인화되지 않았기 때문에 이 쿼리가 성능이 나쁠 것으로 생각할 수 있습니다. 하지만 실제로는 user_id에 대한 인덱스가 충분한 행을 필터링할 수 있기 때문에 쿼리가 정상적으로 수행될 수 있습니다.

인덱스가 재사용되는지 확인하는 가장 좋은 방법은 쿼리를 EXPLAIN ANALYZE를 사용하여 실행하는 것입니다. 조인된 테이블과 필터링에 사용되는 열에 따라 추가적인 인덱스가 큰 차이를 만들지 않는 경우도 있을 수 있습니다.

요약하면 다음과 같습니다.

  1. 가능한 한 기존 인덱스를 재사용하도록 쿼리를 작성하십시오.
  2. EXPLAIN ANALYZE를 사용하여 쿼리를 실행하고 가장 이상적인 쿼리를 찾기 위해 결과를 분석하십시오.

데이터 크기

특히 작은 테이블의 경우 일반적인 시퀀스 스캔(모든 행을 반복하는 것)이 더 빠르므로 데이터베이스는 인덱스를 사용하지 않을 수 있습니다. 테이블이 성장할 것으로 예상되고 쿼리가 많은 행을 필터링해야 하는 경우 인덱스를 추가하는 것을 고려할 수 있습니다. 테이블 크기가 작고(<1,000 레코드) 기존 인덱스가 이미 충분한 행을 필터링하거나 인덱스 추가가후 일정 시간이 지나도 쿼리 시간이 크게 줄어들지 않을 경우 인덱스를 추가하지 않을 수도 있습니다.

유지 관리 오버헤드

인덱스는 모든 테이블 쓰기에 대해 업데이트되어야 합니다. PostgreSQL의 경우 테이블에 데이터를 쓸 때마다 모든 기존 인덱스가 업데이트됩니다. 결과적으로 동일한 테이블에 많은 인덱스가 있으면 쓰기가 느려질 수 있습니다. 따라서 추가적인 인덱스를 유지하는 오버헤드와 쿼리 성능을 균형있게 유지하는 것이 중요합니다.

예를 들어, 새로운 인덱스 추가로 SELECT 시간이 5밀리초 감소하더라도 INSERT/UPDATE/DELETE 시간이 10밀리초 증가한다면 새로운 인덱스가 그렇게 가치있지 않을 수 있습니다. SELECT 시간이 감소하고 INSERT/UPDATE/DELETE 시간이 영향을 받지 않는 경우에 새로운 인덱스가 더 유용합니다.

사용되지 않는 인덱스 찾기

사용되지 않는 인덱스를 확인하려면 다음 쿼리를 실행할 수 있습니다.

SELECT relname as table_name, indexrelname as index_name, idx_scan, idx_tup_read, idx_tup_fetch, pg_size_pretty(pg_relation_size(indexrelname::regclass))
FROM pg_stat_all_indexes
WHERE schemaname = 'public'
AND idx_scan = 0
AND idx_tup_read = 0
AND idx_tup_fetch = 0
ORDER BY pg_relation_size(indexrelname::regclass) desc;

이 쿼리는 사용되지 않는 모든 인덱스를 포함하는 목록을 출력하고 인덱스 크기순으로 정렬합니다. 이 쿼리를 통해 기존 인덱스가 아직 필요한지를 결정하는 데 도움이 됩니다. 각 열의 의미에 대한 자세한 정보는 다음에서 찾을 수 있습니다. https://www.postgresql.org/docs/current/monitoring-stats.html.

프로덕션에서 인덱스가 여전히 사용 중인지 확인하려면 Thanos를 사용하십시오.

sum by (type)(rate(pg_stat_user_indexes_idx_scan{env="gprd", indexrelname="INSERT INDEX NAME HERE"}[30d]))

쿼리 출력이 실제 데이터베이스 사용 상황에 의존하기 때문에 다음과 같은 요인에 영향을 받을 수 있습니다.

  • 특정 쿼리가 절대 실행되지 않아 특정 인덱스를 사용할 수 없는 경우
  • PostgreSQL이 인덱스 스캔 대신 시퀀스 스캔을 사용하는 경우 데이터가 적은 테이블

이 데이터는 자주 사용되는 데이터베이스와 가능한 많은 GitLab 기능을 사용하는 경우에만 신뢰할 수 있습니다.

인덱스의 명명 규칙

마이그레이션 메서드의 암시적 명명 동작에 의존하는 대신, 복잡한 정의를 갖는 인덱스는 명시적으로 명명해야 합니다. 간단히 말해서, 다음 옵션 중 하나 이상을 사용하여 생성된 인덱스에 대해 명시적인 이름 인수를 제공해야 합니다.

  • where
  • using
  • order
  • length
  • type
  • opclass

인덱스 이름을 지정하는 고려 사항

저희의 제약 조건 명명 규칙 페이지를 확인하세요.

명시적인 이름이 필요한 이유

Rails는 데이터베이스에 대해 독립적이므로, 인덱스 이름을 테이블 이름과 열 이름의 필수 옵션에서만 생성합니다. 예를 들어, 다음과 같이 마이그레이션에서 두 개의 인덱스가 생성된다고 상상해보세요:

def up
  add_index :my_table, :my_column

  add_index :my_table, :my_column, where: 'my_column IS NOT NULL'
end

두 번째 인덱스 생성은 실패합니다. 왜냐하면 Rails는 두 인덱스에 대해 동일한 이름을 생성하기 때문입니다.

이 명명 문제는 index_exists? 메서드의 동작에 의해 더욱 복잡해집니다. 이 메서드는 인덱스의 테이블 이름, 열 이름 및 고유성을 고려하여 비교합니다. 예를 들어:

def up
  unless index_exists?(:my_table, :my_column, where: 'my_column IS NOT NULL')
    add_index :my_table, :my_column, where: 'my_column IS NOT NULL'
  end
end

index_exists? 호출은 :my_table:my_column어떠한 인덱스도 존재하면 true를 반환하고 인덱스 생성이 우회됩니다.

add_concurrent_index 도우미는 존재하는 테이블에 인덱스를 생성해야 할 때 요구됩니다. 이는 트랜잭션 마이그레이션 내에서 사용할 수 없으므로 이미 존재하는 인덱스를 감지하는 내장 확인이 있습니다. 일치하는 항목이 발견되면 인덱스 생성이 건너뛰어집니다. 특정 유형의 인덱스에 항상 명시적인 이름을 요구함으로써, 오류 발생 가능성이 크게 줄어듭니다.

인덱스의 존재 여부 확인

인덱스를 이름으로 확인하는 가장 쉬운 방법은 index_name_exists? 메서드를 사용하는 것입니다. 그러나 index_exists? 메서드도 이름 옵션과 함께 사용할 수 있습니다. 예를 들어:

class MyMigration < Gitlab::Database::Migration[2.1]
  INDEX_NAME = 'index_name'

  def up
    # 스키마 불일치로 인해 조건적으로 인덱스를 생성해야 합니다
    unless index_exists?(:table_name, :column_name, name: INDEX_NAME)
      add_index :table_name, :column_name, name: INDEX_NAME
    end
  end

  def down
    # 작업 없음
  end
end

add_concurrent_index, remove_concurrent_index, remove_concurrent_index_by_name과 같은 동시 인덱스 도우미는 이미 내부적으로 존재 확인을 수행합니다.

임시 인덱스

인덱스가 일시적으로 필요한 경우가 있을 수 있습니다.

예를 들어, 마이그레이션 중에 테이블의 열이 조건적으로 업데이트되어야 할 수 있습니다. 쿼리 성능 가이드에서 어떤 열을 업데이트해야 하는지 조회하려면, 그렇지 않으면 사용되지 않을 인덱스가 필요합니다.

이러한 경우, 임시 인덱스를 고려하세요. 임시 인덱스를 지정하려면:

  1. 인덱스 이름을 tmp_로 접두어를 붙이고 명명 규칙을 따릅니다.
  2. 다음 (또는 미래) 마일스톤에서 인덱스를 제거하는 후속 이슈를 생성합니다.
  3. 마이그레이션에 제거 문제를 언급하는 주석을 추가합니다.

임시 마이그레이션은 다음과 같이 보일 것입니다:

INDEX_NAME = 'tmp_index_projects_on_owner_where_emails_disabled'

def up
  # 13.9에서 제거될 임시 인덱스 https://gitlab.com/gitlab-org/gitlab/-/issues/1234
  add_concurrent_index :projects, :creator_id, where: 'emails_disabled = false', name: INDEX_NAME
end

def down
  remove_concurrent_index_by_name :projects, INDEX_NAME
end

일괄 배경 마이그레이션 이전에 새 인덱스를 분석

가끔은 일괄 배경 마이그레이션을 지원하기 위해 새 인덱스를 추가해야할 수 있습니다. 일반적으로, 이것은 두 개의 포스트 배포 마이그레이션을 생성함으로써 수행됩니다:

  1. 새 인덱스 추가, 대개 임시 인덱스입니다.
  2. 일괄 배경 마이그레이션을 대기열에 넣습니다.

대부분의 경우, 추가적인 작업이 필요하지 않습니다. 새 인덱스가 생성되고, 일괄 배경 마이그레이션을 대기열에 넣고 실행할 때 예상대로 사용됩니다.

그러나 표현 인덱스는 생성 시에 새 인덱스의 통계를 생성하지 않습니다. Autovacuum는 결국 ANALYZE를 실행하고 통계를 업데이트하여 새 인덱스가 사용됩니다. 새 인덱스를 생성한 직후에 필요하다면, 위에서 설명한 배경 마이그레이션 시나리오와 같이 ANALYZE를 명시적으로 실행하세요.

새 인덱스 생성 후 ANALYZE를 트리거하기 위해 인덱스 생성 마이그레이션을 테이블을 분석하도록 업데이트하세요:

# db/post_migrate/ 내부에 위치

INDEX_NAME = 'tmp_index_projects_on_owner_and_lower_name_where_emails_disabled'
TABLE = :projects

disable_ddl_transaction!

def up
  add_concurrent_index TABLE, '(creator_id, lower(name))', where: 'emails_disabled = false', name: INDEX_NAME

  connection.execute("ANALYZE #{TABLE}")
end

ANALYZE는 포스트 배포 마이그레이션에서만 실행되어야 하며 큰 테이블을 대상으로해서는 안 됩니다. 만약 이 동작이 더 큰 테이블에서 필요하다면, #database Slack 채널에서 지원을 요청하세요.

파티션화된 테이블에 대한 인덱스

파티션화된 테이블에 대해서는 동시에 인덱스를 만들 수 없습니다. 그러나, 비동시적으로 인덱스를 만들면 해당 테이블에 쓰기 잠금이 걸립니다. 따라서 핫 시스템에서 서비스 중단을 피하려면 인덱스를 만들 때 CONCURRENTLY를 사용해야 합니다.

이를 우회하기 위해 데이터베이스 팀에서 add_concurrent_partitioned_index를 제공했습니다. 이 도우미는 쓰기 잠금을 유지하지 않으면서 파티션화된 테이블에 인덱스를 만듭니다.

실질적으로, add_concurrent_partitioned_index의 작동 방식은 다음과 같습니다.

  1. CONCURRENTLY를 사용하여 각 파티션에 인덱스를 만듭니다.
  2. 부모 테이블에 인덱스를 만듭니다.

Rails 마이그레이션 예시:

# in db/post_migrate/

class AddIndexToPartitionedTable < Gitlab::Database::Migration[2.1]
  include Gitlab::Database::PartitioningMigrationHelpers

  disable_ddl_transaction!

  TABLE_NAME = :table_name
  COLUMN_NAMES = [:partition_id, :id]
  INDEX_NAME = :index_name

  def up
    add_concurrent_partitioned_index(TABLE_NAME, COLUMN_NAMES, name: INDEX_NAME)
  end

  def down
    remove_concurrent_partitioned_index_by_name(TABLE_NAME, INDEX_NAME)
  end
end

비동시적으로 인덱스 만들기

매우 큰 테이블의 경우, 인덱스 생성은 관리가 어려울 수 있습니다. add_concurrent_index는 보통 트래픽을 차단하지 않고 인덱스를 만들지만, 인덱스 생성에 수십 시간이 걸리는 경우 문제가 될 수 있습니다. autovacuum과 같은 필요한 데이터베이스 동작은 실행되지 않을 수 있으며, GitLab.com에서는 인덱스 생성이 완료될 때까지 배포 프로세스가 차단됩니다.

GitLab.com에 미치는 영향을 제한하기 위해 주말에 인덱스 생성을 비동기적으로 처리하는 프로세스가 있습니다. 보통 트래픽과 배포가 적은 주말에 인덱스 생성을 더 낮은 수준의 위험으로 진행할 수 있습니다.

저영향 시간대에 인덱스 생성 일정화

  1. 생성할 인덱스의 일정화.
  2. MR이 배포되고 인덱스가 프로덕션에 존재하는지 확인.
  3. 인덱스를 동기적으로 생성하는 마이그레이션을 추가.

생성할 인덱스의 일정화

  1. 인덱스를 생성하기 위한 포스트-배포 마이그레이션을 포함한 MR을 만듭니다. 이는 비동기적으로 인덱스를 준비합니다.
  2. 후속 이슈를 생성하여, 인덱스를 동기적으로 생성하는 마이그레이션을 추가하는 것입니다.
  3. 비동기 인덱스를 준비하는 MR에 후속 이슈를 언급하는 코멘트를 추가합니다.

비동기적 인덱스 도우미를 사용하여 인덱스를 생성하는 예시는 아래 블록에서 볼 수 있습니다. 해당 마이그레이션은 postgres_async_indexes 테이블에 인덱스 이름과 정의를 입력합니다. 주말에 실행되는 프로세스가 이 테이블에서 인덱스를 가져와 생성을 시도합니다.

# in db/post_migrate/

INDEX_NAME = 'index_ci_builds_on_some_column'

# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/XXXXX에서 동기적으로 생성할 인덱스
def up
  prepare_async_index :ci_builds, :some_column, name: INDEX_NAME
end

def down
  unprepare_async_index :ci_builds, :some_column, name: INDEX_NAME
end

MR이 배포되고 인덱스가 프로덕션에 존재하는지 확인

  1. ChatOps를 사용하여 GitLab.com에서 포스트-배포 마이그레이션이 실행되었는지 확인합니다. /chatops run auto_deploy status <merge_sha>을 사용합니다. 출력이 db/gprd인 경우, 프로덕션 데이터베이스에서 포스트-배포 마이그레이션이 실행된 것입니다. 자세한 정보는 GitLab.com에서 포스트-배포 마이그레이션이 실행되었는지 확인하는 방법을 참조하세요.
  2. 인덱스를 비동기적으로 생성했음의 경우, 다음 주말까지 인덱스가 생성되길 기다립니다.
  3. Database Lab을 사용하여 생성 여부를 확인합니다. 출력에서 해당 인덱스가 invalid로 되어 있지 않은지 확인합니다.

인덱스를 동기적으로 생성하는 마이그레이션을 추가

프로덕션 데이터베이스에 인덱스가 존재함을 확인한 후, 인덱스를 동기적으로 생성하는 두 번째 MR을 만듭니다. 스키마 변경은 이 두 번째 MR에 structure.sql에 업데이트 및 커밋되어야 합니다. 동기적 마이그레이션은 GitLab.com에는 무효 조치가 되지만, 다른 설치에는 예상대로 마이그레이션을 추가해야 합니다. 아래 블록은 이전 비동기적 예시에 대한 두 번째 마이그레이션 생성하는 방법을 보여줍니다.

경고: 동기적으로 인덱스를 생성하기 전에 프로덕션에 인덱스가 존재하는지 확인하세요. 두 번째 마이그레이션이 인덱스가 생성되기 전에 배포되면, 두 번째 마이그레이션이 실행될 때 인덱스가 동기적으로 생성됩니다.

# in db/post_migrate/

INDEX_NAME = 'index_ci_builds_on_some_column'

disable_ddl_transaction!

def up
  add_concurrent_index :ci_builds, :some_column, name: INDEX_NAME
end

def down
  remove_concurrent_index_by_name :ci_builds, INDEX_NAME
end

로컬에서 데이터베이스 인덱스 변경 사항 테스트

병합 요청을 생성하기 전에 반드시 로컬에서 데이터베이스 인덱스 변경 사항을 테스트해야 합니다.

비동기적으로 생성된 인덱스 확인

로컬 환경에서 비동기적으로 인덱스 도우미를 사용하여 인덱스를 생성하는 변경 사항을 테스트하려면 다음을 수행하세요:

  1. Rails 콘솔에서 Feature.enable(:database_async_index_creation)Feature.enable(:database_reindexing)을 실행하여 기능 플래그를 활성화합니다.
  2. bundle exec rails db:migrate를 실행하여 postgres_async_indexes 테이블에 항목을 생성합니다.
  3. bundle exec rails gitlab:db:execute_async_index_operations:all을 실행하여 모든 데이터베이스에서 인덱스가 비동기적으로 생성되도록 합니다.
  4. 인덱스를 확인하려면 GDK 명령인 gdk psql을 사용하여 PostgreSQL 콘솔을 열고 명령 \d <index_name>을 실행하여 새로 생성된 인덱스가 있는지 확인합니다.

인덱스를 비동기적으로 제거

매우 큰 테이블에 대해 인덱스 제거는 관리가 어려울 수 있습니다. remove_concurrent_index는 일반 트래픽을 차단하지 않고 인덱스를 제거하지만, 몇 시간 동안 인덱스 제거가 실행되면 문제가 발생할 수 있습니다. autovacuum과 같은 필수 데이터베이스 작업을 실행할 수 없으며, GitLab.com의 배포 프로세스는 인덱스 제거가 완료될 때까지 차단됩니다.

GitLab.com에 미치는 영향을 제한하려면 주말 시간에 인덱스를 비동기적으로 제거하기 위한 다음 프로세스를 사용하십시오. 보통 트래픽이 적고 배포도 적기 때문에, 인덱스 제거는 더 낮은 수준의 위험에서 진행될 수 있습니다.

  1. 인덱스 제거 일정 설정.
  2. MR이 배포되었고 인덱스가 프로덕션에 더 이상 존재하지 않는지 확인.
  3. 인덱스를 동기적으로 제거하는 마이그레이션 추가.

인덱스 제거 일정 설정

  1. 인덱스를 비동기적으로 제거하기 위한 포스트 배포 마이그레이션을 포함한 병합 요청을 생성합니다.
  2. 추후 문제를 생성하여 인덱스를 동기적으로 제거하는 마이그레이션을 추가합니다.
  3. 비동기적인 인덱스 제거를 준비하는 병합 요청에, 추후 문제를 언급하는 코멘트를 추가합니다.

예를 들어, 비동기적으로 인덱스를 제거하려면:

# in db/post_migrate/

INDEX_NAME = 'index_ci_builds_on_some_column'

# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/XXXXX에서 동기적으로 제거할 인덱스
def up
  prepare_async_index_removal :ci_builds, :some_column, name: INDEX_NAME
end

def down
  unprepare_async_index :ci_builds, :some_column, name: INDEX_NAME
end

이 마이그레이션은 인덱스 이름과 정의를 postgres_async_indexes 테이블에 입력합니다. 주말에 실행되는 프로세스는 이 테이블에서 인덱스를 가져와 제거를 시도합니다.

병합 요청 설명에 테스트한 데이터베이스 인덱스 변경 사항을 반드시 포함하여 병합 요청을 생성하기 전 로컬에서 데이터베이스 인덱스 변경 사항을 테스트해야 합니다.

MR이 배포되었고 인덱스가 프로덕션에 더 이상 존재하지 않는지 확인

  1. ChatOps를 사용하여 GitLab.com에서 포스트 배포 마이그레이션이 실행되었는지 확인하려면 /chatops run auto_deploy status <merge_sha>을 실행합니다. 출력이 db/gprd로 나오면, 포스트 배포 마이그레이션이 프로덕션 데이터베이스에서 실행되었습니다. 자세한 정보는 How to determine if a post-deploy migration has been executed on GitLab.com를 참조하세요.
  2. 인덱스를 비동기적으로 제거했을 경우, 다음 주말까지 기다려서 인덱스가 주말에 제거되도록 합니다.
  3. 제거가 성공적으로 이루어졌는지 확인하기 위해 Database Lab을 사용합니다. Database Lab 에서 제거된 인덱스를 찾을 때 오류가 발생해야 합니다. 그렇지 않으면, 해당 인덱스가 아직 존재할 수 있습니다.

인덱스를 동기적으로 제거하는 마이그레이션 추가

인덱스가 프로덕션 데이터베이스에 더 이상 존재하지 않음을 확인한 후, 인덱스를 동기적으로 제거하는 두 번째 병합 요청을 생성하세요. 스키마 변경 사항은 두 번째 병합 요청의 structure.sql에 업데이트되고 커밋되어야 합니다. 동기적인 마이그레이션은 GitLab.com에는 영향을 미치지 않지만, 기대되는 대로 다른 설치에 대해 마이그레이션을 추가해야 합니다. 이전 비동기적인 예제에 대한 두 번째 마이그레이션을 생성하는 예시는 다음과 같습니다:

경고: 인덱스가 제거된 것이 프로덕션에서 더 이상 존재하지 않는지 확인한 후 remove_concurrent_index_by_name으로 두 번째 마이그레이션을 병합하기 전에 확인하세요. 두 번째 마이그레이션이 인덱스가 제거되기 전에 배포된 경우에는 두 번째 마이그레이션이 실행될 때 인덱스가 동기적으로 제거됩니다.

# in db/post_migrate/

INDEX_NAME = 'index_ci_builds_on_some_column'

disable_ddl_transaction!

def up
  remove_concurrent_index_by_name :ci_builds, name: INDEX_NAME
end

def down
  add_concurrent_index :ci_builds, :some_column, name: INDEX_NAME
end

비동기적으로 제거된 인덱스 확인

인덱스를 제거하는 변경 사항을 테스트하려면 로컬 환경에서 비동기 인덱스 도우미를 사용하십시오:

  1. 레일즈 콘솔에서 Feature.enable(:database_reindexing)를 실행하여 기능 플래그를 활성화합니다.
  2. bundle exec rails db:migrate를 실행하여 postgres_async_indexes 테이블에 항목을 만듭니다.
  3. bundle exec rails gitlab:db:reindex를 실행하여 인덱스를 비동기적으로 제거합니다.
  4. 인덱스를 확인하려면 GDK 명령인 gdk psql을 사용하여 PostgreSQL 콘솔을 열고, 파괴된 인덱스가 더 이상 존재하지 않는지 확인하려면 \d <index_name>을 실행합니다.