인덱스 테이블 패턴

Azure Storage

쿼리에서 자주 참조하는 데이터 저장소의 필드에 대한 인덱스를 만듭니다. 이 패턴은 애플리케이션이 데이터 저장소에서 검색할 데이터를 더 빠르게 찾을 수 있도록 하여 쿼리 성능을 향상시킬 수 있습니다.

컨텍스트 및 문제점

많은 데이터 저장소는 기본 키를 사용하여 엔터티 컬렉션에 대한 데이터를 구성합니다. 애플리케이션은 이 키를 사용하여 데이터를 찾고 검색할 수 있습니다. 이 그림은 고객 정보를 보관하는 데이터 저장소의 예를 보여줍니다. 기본 키는 고객 ID입니다. 이 그림은 기본 키(고객 ID)로 구성된 고객 정보를 보여 줍니다.

그림 1 - 기본 키로 구성된 고객 정보(고객 ID)

기본 키는 이 키의 값을 기반으로 데이터를 가져오는 쿼리에 유용하지만 다른 필드를 기반으로 데이터를 검색해야 하는 경우 애플리케이션에서 기본 키를 사용하지 못할 수 있습니다. 고객 예제에서 애플리케이션은 고객이 있는 마을과 같은 다른 특성의 값을 참조하여 데이터를 쿼리하는 경우 고객 ID 기본 키를 사용하여 고객을 검색할 수 없습니다. 이와 같은 쿼리를 수행하려면 애플리케이션이 모든 고객 레코드를 가져오고 검사해야 할 수 있으며, 이는 느린 프로세스일 수 있습니다.

많은 관계형 데이터베이스 관리 시스템은 보조 인덱스를 지원합니다. 보조 인덱스는 하나 이상의 기본이 아닌(보조) 키 필드로 구성되는 별도의 데이터 구조이며, 각 인덱스 값의 데이터가 어디에 저장되어 있는지를 나타냅니다. 보조 인덱스의 항목은 일반적으로 보조 키의 값을 기준으로 정렬되어 데이터를 빠르게 조회할 수 있습니다. 이러한 인덱스는 일반적으로 데이터베이스 관리 시스템에서 자동으로 기본.

애플리케이션이 수행하는 다양한 쿼리를 지원하는 데 필요한 만큼의 보조 인덱스를 만들 수 있습니다. 예를 들어 고객 ID가 기본 키인 관계형 데이터베이스의 Customers 테이블에서 애플리케이션이 상주하는 마을에서 고객을 자주 조회하는 경우 마을 필드에 보조 인덱스 추가가 유용합니다.

그러나 보조 인덱스는 관계형 시스템에서 일반적이지만 클라우드 애플리케이션에서 사용하는 일부 NoSQL 데이터 저장소는 동일한 기능을 제공하지 않습니다.

솔루션

데이터 저장소에서 보조 인덱스를 지원하지 않는 경우 사용자 고유의 인덱스 테이블을 만들어 수동으로 에뮬레이트할 수 있습니다. 인덱스 테이블은 지정된 키로 데이터를 구성합니다. 필요한 보조 인덱스 수와 애플리케이션이 수행하는 쿼리의 특성에 따라 인덱스 테이블을 구조화하는 데 일반적으로 세 가지 전략이 사용됩니다.

첫 번째 전략은 데이터를 각각의 인덱스 테이블에 복제하고 다른 키로 구성하는 것입니다(완전 역정규화). 다음 그림에서는 Town 및 LastName별로 동일한 고객 정보를 구성하는 인덱스 테이블을 보여 줍니다.

그림 2 - 데이터가 각 인덱스 테이블에 중복됨

이 전략은 데이터가 각 키를 사용하여 쿼리된 횟수에 비해 상대적으로 정적인 경우에 적합합니다. 데이터가 더 동적이면 각 인덱스 테이블을 기본 처리 오버헤드가 너무 커서 이 방법이 유용하지 않습니다. 또한 데이터 볼륨이 매우 큰 경우 중복 데이터를 저장하는 데 필요한 공간의 양이 중요합니다.

두 번째 전략은 다음 그림에서처럼 다른 키로 구성되는 정규화된 인덱스 테이블을 생성하고 데이터를 복제하기보다 기본 키를 사용해 원본 데이터를 참조하는 것입니다. 원래 데이터를 팩트 테이블이라고 합니다.

그림 3 - 각 인덱스 테이블에서 데이터를 참조합니다.

이 기법은 공간을 절약하고 복제 데이터를 유지하는 오버헤드를 줄인다는 장점이 있습니다. 단점은 애플리케이션이 보조 키를 사용하여 데이터를 찾기 위해 두 가지 조회 작업을 수행해야 한다는 것입니다. 인덱스 테이블의 데이터에 대한 기본 키를 찾은 다음 기본 키를 사용하여 팩트 테이블의 데이터를 조회해야 합니다.

세 번째 전략은 자주 검색되는 필드를 복제하는 여러 키로 구성된 부분적으로 정규화된 인덱스 테이블을 만드는 것입니다. 자주 액세스하지 않은 필드에 액세스하려면 팩트 테이블을 참조하세요. 다음 그림에서는 일반적으로 액세스되는 데이터가 각 인덱스 테이블에서 중복되는 방법을 보여 있습니다.

그림 4 - 일반적으로 액세스되는 데이터는 각 인덱스 테이블에 중복됩니다.

이 전략을 사용하면 첫 번째 접근 방식과 두 번째 접근 방식 사이에 균형을 유지할 수 있습니다. 일반적인 쿼리에 대한 데이터는 단일 조회를 사용하여 신속하게 검색할 수 있지만 공간 및 기본테넌스 오버헤드는 전체 데이터 집합을 복제하는 것만큼 중요하지 않습니다.

애플리케이션이 값의 조합(예: "Redmond에 살고 성이 Smith인 모든 고객 찾기")을 지정해 데이터를 자주 쿼리하는 경우, 인덱스 테이블의 항목에 대한 키를 Town 특성과 LastName 특성의 연결로 구현할 수 있습니다. 다음 그림은 복합 키를 기준으로 하는 인덱스 테이블을 보여 줍니다. 키는 먼저 Town을 기준으로 정렬된 다음, Town의 값이 동일한 레코드에 대해 LastName을 기준으로 정렬됩니다.

그림 5 - 복합 키를 기반으로 하는 인덱스 테이블

인덱스 테이블은 분할된 데이터에 대한 쿼리 작업의 속도를 높일 수 있으며 분할된 키가 해시되는 경우에 특히 유용합니다. 다음 그림에서는 분할된 데이터베이스 키가 고객 ID의 해시인 예제를 보여줍니다. 인덱스 테이블은 해시되지 않은 값(Town 및 LastName)으로 데이터를 구성하고 해시된 분할된 데이터베이스 키를 조회 데이터로 제공할 수 있습니다. 이렇게 하면 범위 내에 속하는 데이터를 검색해야 하거나 해시되지 않은 키 순서로 데이터를 가져와야 하는 경우 애플리케이션이 해시 키(비용이 많이 드는 작업)를 반복적으로 계산하지 못하게 할 수 있습니다. 예를 들어 "Redmond에 사는 모든 고객 찾기"와 같은 쿼리는 인덱스 테이블에서 일치하는 항목을 찾아 신속하게 해결할 수 있습니다(일치하는 항목은 모두 연속 블록에 저장됨). 그런 다음 인덱스 테이블에 저장된 분할 키를 사용하여 고객 데이터에 대한 참조를 따릅니다.

그림 6 - 분할된 데이터에 대한 빠른 조회를 제공하는 인덱스 테이블

문제 및 고려 사항

이 패턴을 구현할 방법을 결정할 때 다음 사항을 고려하세요.

  • 보조 인덱스를 기본 오버헤드가 클 수 있습니다. 애플리케이션에서 사용하는 쿼리를 분석하고 이해해야 합니다. 정기적으로 사용될 가능성이 있는 경우에만 인덱스 테이블을 만듭니다. 애플리케이션이 수행하지 않거나 가끔만 수행하는 쿼리를 지원하기 위해 투기적 인덱스 테이블을 만들지 마세요.

  • 인덱스 테이블의 데이터를 복제하면 스토리지 비용과 여러 데이터 복사본을 기본 데 필요한 노력에 상당한 오버헤드가 발생할 수 있습니다.

  • 인덱스 테이블을 원래 데이터를 참조하는 정규화된 구조로 구현하려면 애플리케이션에서 데이터를 찾기 위해 두 가지 조회 작업을 수행해야 합니다. 첫 번째 작업은 인덱스 테이블을 검색하여 기본 키를 검색하고, 두 번째 작업은 기본 키를 사용하여 데이터를 가져옵니다.

  • 시스템이 매우 큰 데이터 집합에 여러 인덱스 테이블을 통합하는 경우 인덱스 테이블과 원래 데이터 간의 일관성을 기본 파악하기 어려울 수 있습니다. 최종 일관성 모델을 중심으로 애플리케이션을 디자인할 수 있습니다. 예를 들어 데이터를 삽입, 업데이트 또는 삭제하기 위해 애플리케이션은 메시지를 큐에 게시하고 별도의 태스크가 작업을 수행하고 이 데이터를 비동기적으로 참조하는 인덱스 테이블을 기본 수 있습니다. 최종 일관성을 구현하는 방법에 대한 자세한 내용은 데이터 일관성 입문을 참조 하세요.

    Microsoft Azure Storage 테이블은 동일한 파티션(엔터티 그룹 트랜잭션이라고 함)에 보관된 데이터에 대한 변경 내용에 대한 트랜잭션 업데이트를 지원합니다. 팩트 테이블과 하나 이상의 인덱스 테이블에 대한 데이터를 동일한 파티션에 저장할 수 있는 경우 이 기능을 사용하여 일관성을 유지할 수 있습니다.

  • 인덱스 테이블 자체는 분할되거나 분할될 수 있습니다.

이 패턴을 사용해야 하는 경우

이 패턴은 애플리케이션이 기본(또는 분할) 키가 아닌 다른 키를 사용해 데이터를 자주 검색해야 할 때 쿼리 성능을 높이기 위해 사용합니다.

다음의 경우에는 이 패턴이 유용하지 않습니다.

  • 데이터가 휘발성인 경우. 인덱스 테이블은 매우 빠르게 만료되어 비효율적이거나기본 인덱스 테이블을 사용하여 절감한 것보다 큰 오버헤드를 만들 수 있습니다.
  • 인덱스 테이블의 보조 키로 선택한 필드는 차별이 없으며 작은 값 집합(예: 성별)만 가질 수 있습니다.
  • 인덱스 테이블의 보조 키로 선택한 필드에 대한 데이터 값의 균형은 매우 왜곡됩니다. 예를 들어 레코드의 90%가 하나의 필드에서 동일한 값을 포함하면 이 필드를 기준으로 데이터를 조회하기 위해 인덱스 테이블을 생성하고 유지하는 것이 데이터 전체를 순차적으로 스캔하는 것보다 많은 오버헤드를 초래할 수 있습니다. 그러나 쿼리가 다시 기본 10%에 있는 값을 매우 자주 대상으로 지정하는 경우 이 인덱스가 유용할 수 있습니다. 애플리케이션이 수행하는 쿼리와 수행 빈도를 이해해야 합니다.

워크로드 디자인

설계자는 인덱스 테이블 패턴을 워크로드 디자인에 사용하여 Azure Well-Architected Framework 핵심 요소에서 다루는 목표와 원칙을 해결하는 방법을 평가해야 합니다. 예시:

핵심 요소 이 패턴이 핵심 목표를 지원하는 방법
안정성 디자인 결정은 워크로드가 오작동에 대한 복원력을 갖도록 하고 오류가 발생한 후 완전히 작동하는 상태로 복구 되도록 하는 데 도움이 됩니다. 클라이언트는 조회 프로세스를 통해 분할, 파티션 또는 엔드포인트를 가리키므로 이 패턴을 사용하여 데이터 액세스에 대한 장애 조치(failover) 방법을 용이하게 할 수 있습니다.

- RE:06 데이터 분할
- RE:09 재해 복구
성능 효율성은 크기 조정, 데이터, 코드의 최적화를 통해 워크로드가 수요를 효율적으로 충족하는 데 도움이 됩니다. 클라이언트는 성능 최적화를 위해 동적 데이터 분할을 사용하도록 설정할 수 있는 분할, 파티션 또는 엔드포인트를 가리켰습니다.

- PE:05 크기 조정 및 분할
- PE:08 데이터 성능

디자인 결정과 마찬가지로 이 패턴으로 도입될 수 있는 다른 핵심 요소의 목표에 대한 절충을 고려합니다.

예시

Azure Storage 테이블은 클라우드에서 실행 중인 애플리케이션에 대한 확장성이 뛰어난 키/값 데이터 스토리지를 제공합니다. 애플리케이션은 키를 지정하여 데이터 값을 저장하고 검색합니다. 데이터 값에는 여러 필드가 포함될 수 있지만 데이터 항목의 구조는 테이블 스토리지에 불투명하므로 데이터 항목을 바이트 배열로 처리하기만 하면 됩니다.

Azure Storage 테이블은 분할도 지원합니다. 분할 키에는 파티션 키와 행 키라는 두 가지 요소가 포함됩니다. 동일한 파티션 키가 있는 항목은 동일한 파티션(분할된 데이터베이스)에 저장되고 항목은 분할된 데이터베이스 내에서 행 키 순서로 저장됩니다. Table Storage는 파티션 내의 연속된 행 키 값 범위 내에 속하는 데이터를 가져오는 쿼리를 수행하는 데 최적화되어 있습니다. Azure 테이블에 정보를 저장하는 클라우드 애플리케이션을 빌드하는 경우 이 기능을 염두에 두고 데이터를 구성해야 합니다.

예를 들어 영화에 대한 정보를 저장하는 애플리케이션을 고려해 보세요. 애플리케이션은 장르별로 영화를 자주 쿼리합니다(액션, 다큐멘터리, 기록, 코미디, 드라마 등). 다음 그림과 같이 장르를 파티션 키로 사용하고 영화 이름을 행 키로 지정하여 각 장르에 대한 파티션이 있는 Azure 테이블을 만들 수 있습니다.

그림 7 - Azure 테이블에 저장된 동영상 데이터

이 방법은 애플리케이션이 행위자 별표로 영화를 쿼리해야 하는 경우에도 효과적이지 않습니다. 이 경우 인덱스 테이블 역할을 하는 별도의 Azure 테이블을 만들 수 있습니다. 파티션 키는 행위자이고 행 키는 영화 이름입니다. 각 행위자의 데이터는 별도의 파티션에 저장됩니다. 영화가 둘 이상의 배우에 출연하는 경우 동일한 영화가 여러 파티션에서 발생합니다.

영화 데이터는 위의 해결 방법 섹션에서 설명한 첫 번째 접근 방식을 채택해 각 파티션에 보관되는 값에 복제할 수 있습니다. 그러나 각 영화가 여러 번 복제본(replica)(각 행위자에 대해 한 번) 더 효율적일 수 있으므로 가장 일반적인 쿼리(예: 다른 행위자의 이름)를 지원하기 위해 데이터를 부분적으로 비정규화하고 애플리케이션이 장르 파티션에서 전체 정보를 찾는 데 필요한 파티션 키를 포함하여 다시 기본 세부 정보를 검색할 수 있도록 하는 것이 더 효율적일 수 있습니다. 이 방법은 솔루션 섹션의 세 번째 옵션에 설명되어 있습니다. 다음 그림은 이런 접근 방식을 보여 줍니다.

그림 8 - 영화 데이터의 인덱스 테이블 역할을 하는 행위자 파티션

다음 단계

  • Data Consistency Primer(데이터 일관성 입문서). 인덱스 테이블은 기본 인덱싱하는 데이터가 변경될 때 표시되어야 합니다. 클라우드에서는 데이터를 수정하는 동일한 트랜잭션의 일부로 인덱스를 업데이트하는 작업을 수행할 수 없거나 적절하지 않을 수 있습니다. 이 경우 최종적으로 일관된 접근 방식이 더 적합합니다. 최종 일관성과 관련된 문제에 대한 정보를 제공합니다.

이 패턴을 구현할 때 다음 패턴도 관련이 있을 수 있습니다.

  • 분할 패턴입니다. 인덱스 테이블 패턴은 분할된 데이터베이스를 사용하여 분할된 데이터와 함께 자주 사용됩니다. 분할 패턴은 데이터 저장소를 분할된 데이터베이스 집합으로 분할하는 방법에 대한 추가 정보를 제공합니다.
  • 구체화된 뷰 패턴. 데이터를 요약하는 쿼리를 지원하기 위한 데이터 인덱싱 대신 데이터의 구체화된 뷰를 생성하는 것이 더 적절할 수 있습니다. 데이터에 대해 미리 채워진 뷰를 생성하여 효율적인 요약 쿼리를 지원하는 방법을 설명합니다.