구체화된 뷰 패턴

데이터가 필요한 쿼리 작업에 이상적으로 형식이 지정되지 않은 경우 하나 이상의 데이터 저장소에 있는 데이터에 대해 미리 채워진 뷰를 생성합니다. 이 방법은 효율적인 쿼리 및 데이터 추출을 지원하고 애플리케이션 성능을 향상시킬 수 있습니다.

컨텍스트 및 문제점

데이터를 저장할 때 개발자와 데이터 관리자는 데이터를 읽는 방법보다는 데이터를 저장하는 방법에 우선 순위를 두는 경우가 많습니다. 선택한 스토리지 형식은 일반적으로 데이터의 형식, 데이터 크기 및 데이터 무결성을 관리하기 위한 요구 사항 및 사용 중인 저장소 종류를 반영합니다. 예를 들어 NoSQL 문서 저장소를 사용하는 경우 해당 엔터티에 대한 모든 정보를 포함하는 일련의 집계로 데이터를 나타내는 경우가 많습니다.

그러나 이 방법은 쿼리에 부정적인 영향을 미칠 수 있습니다. 쿼리에 주문 세부 정보가 없는 여러 고객에 대한 주문 요약과 같은 일부 엔터티의 데이터 하위 집합만 필요한 경우 필요한 정보를 얻으려면 관련 엔터티에 대한 모든 데이터를 추출해야 합니다.

읽기 시간에 인덱스를 추가하거나 쿼리를 재구성해도 이러한 비효율성이 항상 해결되는 것은 아닙니다. 쓰기 성능에 영향을 주지 않고는 임의 읽기 패턴에 대해 많은 저장소를 다시 인덱싱할 수 없습니다. 엔터티 간 집계는 쿼리 시점에 여전히 비용이 많이 발생합니다. 일부 저장소에는 의도적으로 제한된 쿼리 기능이 있습니다. 이러한 제약 조건으로 인해 원본 저장소 내에서만 읽기 경로를 최적화하는 것은 종종 충분하지 않습니다.

해결 방법

효율적인 쿼리를 지원하기 위해 일반적인 솔루션은 필요한 결과 집합에 적합한 형식으로 데이터를 구체화하는 뷰를 미리 생성하는 것입니다. 구체화된 뷰 패턴은 원본 데이터가 쿼리에 적합한 형식이 아니거나, 적절한 쿼리를 생성하기 어렵거나, 데이터 또는 데이터 저장소의 특성으로 인해 쿼리 성능이 저하되는 환경에서 미리 채워진 데이터 뷰를 생성하는 방법을 설명합니다.

이 패턴에서 구체화된 뷰 는 하나 이상의 원본 저장소에서 파생된 데이터를 유지하는 읽기 모델 또는 프로젝션입니다. 전용 애플리케이션 구성 요소 또는 데이터 파이프라인은 저장소 경계를 넘어 프로젝션을 유지할 수 있습니다. 쿼리 소비자는 프로젝션을 읽기 전용으로 처리합니다. 이 아키텍처 개념은 데이터베이스 엔진이 자체 기능 제약 조건에 따라 정의, 저장 및 새로 고침하는 데이터베이스 네이티브 구체화된 뷰 개체보다 더 광범위합니다.

쿼리에 필요한 데이터만 포함하는 이러한 구체화된 뷰를 통해 애플리케이션은 필요한 정보를 신속하게 얻을 수 있습니다. 구체화된 뷰에는 테이블을 조인하거나 데이터 엔터티를 결합하는 것 외에도 계산 열 또는 데이터 항목의 현재 값, 데이터 항목에 대한 값을 결합하거나 변환을 실행한 결과 및 쿼리의 일부로 지정된 값이 포함될 수 있습니다. 구체화된 뷰는 단일 쿼리에 최적화될 수도 있습니다.

핵심은 구체화된 뷰와 포함된 데이터는 원본 데이터 저장소에서 완전히 다시 작성할 수 있으므로 완전히 삭제할 수 있다는 것입니다. 쿼리 소비자는 보기를 직접 업데이트하지 않습니다. 대신 전용 구성 요소, 데이터 파이프라인 또는 데이터베이스 엔진이 유지 관리하므로 특수 캐시입니다.

뷰의 원본 데이터가 변경되면 새 정보를 포함하도록 뷰가 업데이트되어야 합니다. 이 업데이트가 자동으로 수행되도록 예약하거나 시스템에서 원래 데이터의 변경 내용을 감지할 때 예약할 수 있습니다. 경우에 따라 뷰를 수동으로 다시 생성해야 할 수 있습니다. 다음 그림에서는 구체화된 뷰 패턴을 사용하는 방법의 예를 보여 줍니다.

구체화된 뷰 패턴을 사용하는 방법의 예를 보여 주는 다이어그램

문제 및 고려 사항

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

  • 새로 고침 전략을 봅니다. 이 방법은 원본 데이터가 빠르게 변경되는 경우 과도한 오버헤드가 발생할 수 있지만 원본 데이터 변경을 나타내는 이벤트에 대한 응답으로 뷰가 다시 생성되는 것이 이상적입니다. 또는 예약된 작업, 외부 트리거 또는 수동 작업을 사용하여 보기를 다시 생성하는 것이 좋습니다.

  • 새로 고침 동작. 구현이 전체 다시 빌드를 수행하는지 또는 변경 내용을 증분 방식으로 적용하는지 확인합니다. 또한 새로 고침 작업이 읽기 작업을 차단하는지 여부를 결정해야 합니다.

    이러한 결정은 쿼리가 잠재적으로 부실한 구체화된 데이터를 반환할지, 처리되지 않은 원본 변경 내용과 구체화된 데이터를 결합하여 현재 결과를 반환할지, 아니면 새로 고침이 완료될 때까지 마지막 전체 버전을 계속 제공할지를 결정합니다.

  • 신호 안정성을 새로 고칩니다. 보기 재생을 트리거하는 활성화 신호가 손실되거나 지연되는 경우(예: 누락된 변경 피드 이벤트 또는 실패한 예약된 작업) 보기는 부실 결과를 자동으로 제공합니다. 새로 고침 최신성을 모니터링하고 뷰의 경과 시간이 허용 가능한 최신성 저하 범위를 초과하면 경고를 표시합니다.

  • 컴퓨팅 비용 새로 고침 뷰를 다시 생성하면 원본 데이터의 볼륨 및 변환의 복잡성에 비례하는 컴퓨팅 리소스가 소비됩니다. 빠르게 변화하는 원본 데이터에 대한 이벤트 기반 새로 고침 또는 대규모 분석 뷰의 전체 다시 빌드의 경우 새로 고침의 컴퓨팅 비용이 상당한 비용 동인일 수 있습니다. 새로 고침 빈도 및 범위의 크기를 조정하여 컴퓨팅 지출과 데이터 새로 고침의 균형을 조정합니다.

  • 이벤트 소싱 종속성 일부 시스템에서는 이벤트 소싱 패턴을 사용하여 데이터를 수정한 이벤트만 저장소를 유지하는 경우와 같이 구체화된 뷰가 일반적으로 필요합니다. 현재 상태를 확인하기 위해 모든 이벤트를 검사하여 뷰를 미리 채우면 이벤트 저장소에서 정보를 얻을 수 있습니다. 이벤트 소싱을 사용하지 않는 경우 구체화된 뷰가 유용한지 여부를 고려합니다. 구체화된 뷰는 하나 또는 적은 수의 쿼리에 맞게 특별히 조정되는 경향이 있습니다. 많은 쿼리를 사용하는 경우, 구체화된 뷰는 수용하기 어려운 수준의 스토리지 용량 요구 사항과 스토리지 비용을 초래할 수 있습니다.

  • 데이터 일관성. 뷰를 생성할 때와 이 프로세스가 일정에 따라 발생하는 경우 뷰를 업데이트할 때 데이터 일관성에 미치는 영향을 고려합니다. 뷰가 생성될 때 원본 데이터가 동시에 변경되는 경우 뷰에 있는 데이터의 복사본이 원래 데이터와 완전히 일치하지 않습니다. 최대 부실 기간은 새로 고침 간격 또는 이벤트 처리 지연의 직접적인 결과이므로 이벤트 기반, 예약된 새로 고침 또는 수동 새로 고침 중에서 선택하기 전에 허용되는 부실을 정의합니다.

  • 스토리지 위치를 봅니다. 뷰는 원래 데이터와 동일한 저장소 또는 파티션에 있을 필요가 없습니다. 몇 가지 다른 파티션의 하위 집합을 결합할 수 있습니다.

  • 손실 시 다시 빌드합니다. 뷰는 유실된 경우 다시 빌드할 수 있습니다. 따라서 뷰가 일시적이며 데이터의 현재 상태를 반영하여 쿼리 성능을 향상시키는 데만 사용되는 경우 또는 확장성을 향상시키기 위해 캐시 또는 덜 신뢰할 수 있는 위치에 저장할 수 있습니다.

    그러나 새로 고침 프로세스 자체가 중간에 실패하는 경우(예: 예약된 다시 생성 작업이 충돌하는 경우) 워크로드가 이전 전체 보기, 부분적으로 업데이트된 뷰 또는 다시 생성이 성공할 때까지 뷰를 전혀 제공하지 않아야 하는지 여부를 결정합니다.

    가장 안전한 접근 방식은 일반적으로 원자적 게시 또는 버전 지정 교체이며, 이 경우 워크로드는 새 뷰를 빌드하고 검증하는 동안 마지막으로 완성된 뷰를 계속 제공하고 사용합니다. 유효성 검사가 완료된 후 새 보기로 바꿉니다.

  • 계산된 열. 구체화된 뷰를 정의할 때 기존 데이터 항목의 계산 또는 변환, 쿼리에 전달된 값 또는 적절한 경우 이러한 값의 조합에 따라 데이터 항목 또는 열을 추가하여 해당 값을 최대화합니다.

  • 인덱싱을 봅니다. 스토리지 메커니즘이 지원하는 경우 구체화된 뷰를 인덱싱하여 성능을 더 높이는 것이 좋습니다. 많은 관계형 데이터베이스는 뷰에 대한 인덱싱을 지원합니다. 그러나 보기의 인덱스 유지 관리는 각 새로 고침 주기 동안 쓰기 경로 오버헤드를 추가하므로 추가 새로 고침 시간 및 컴퓨팅 비용과 읽기 성능 향상의 균형을 유지합니다.

  • 뷰에 대한 액세스 제어 구체화된 뷰를 사용하여 보안 또는 개인 정보 보호와 같은 특정 소비자에게 표시되는 데이터 하위 집합을 제한하는 경우 뷰 저장소는 원본 데이터와 동일하거나 엄격한 액세스 제어를 적용해야 합니다. 의도한 범위를 벗어난 데이터를 실수로 포함하는 뷰는 보호된 데이터를 노출할 수 있으므로 새로 고침 파이프라인은 의도하지 않은 열 또는 행을 제외해야 합니다.

  • 뷰의 데이터 수명 주기입니다. 구체화된 모든 뷰에 원본 데이터의 보존 및 삭제 요구 사항을 적용합니다. 필요한 기간 내에 원본 삭제 및 수정을 전파하고 규정 준수 모니터링에 각 보기를 포함합니다. 자세한 내용은 Microsoft Purview 있는 데이터 거버넌스 및 보안 기준을 참조하세요.

  • 수명 주기 관리를 봅니다. 뷰 정의는 특히 뷰가 선언적으로 정의된 경우 소스 제어 및 CI/CD 파이프라인을 통해 관리되는 배포 가능한 아티팩트로 처리합니다. 수명 주기 관리가 없으면 뷰 정의가 환경 간에 드리프트되어 개발, 스테이징 및 프로덕션 전반에서 일관되지 않은 쿼리 동작이 발생할 수 있습니다.

이 패턴을 사용하는 경우

다음과 같은 경우 이 패턴을 사용합니다.

  • 직접 쿼리하기 어렵거나 정규화되거나 반구조화되거나 구조화되지 않은 방식으로 저장된 데이터를 추출하기 위해 쿼리가 매우 복잡해야 하는 데이터에 대한 뷰를 만들어야 합니다.
  • 쿼리 성능을 향상시키는 다시 작성 가능하거나 일시적인 캐시 프로젝션을 만들거나 UI, 보고서 또는 표시에 대한 데이터 전송 개체를 생성하는 데 사용되는 셰이프 데이터를 만들려고 합니다.
  • 데이터 저장소에 항상 연결할 수 없는 환경에서 간헐적 연결 또는 오프라인 시나리오를 지원해야 합니다. 이 경우 뷰를 로컬로 캐시할 수 있습니다.
  • 원본 데이터 형식에 대한 지식이 필요하지 않은 방식으로 쿼리를 단순화하고 실험용 데이터를 노출하려고 합니다. 예를 들어 하나 이상의 데이터베이스 또는 NoSQL 저장소에 있는 하나 이상의 도메인에 서로 다른 테이블을 조인한 다음 최종 용도에 맞게 데이터의 서식을 지정합니다.
  • 보안 또는 개인 정보 보호를 위해 일반적으로 액세스할 수 없거나 수정할 수 있거나 사용자에게 완전히 노출되어서는 안 되는 원본 데이터의 특정 하위 집합에 대한 액세스를 제공하려고 합니다.
  • 개별 기능을 활용하기 위해 다른 데이터 저장소를 연결하려고 합니다. 예를 들어 참조 데이터 저장소로 작성하는 데 효율적인 클라우드 저장소와 구체화된 뷰를 보유하는 좋은 쿼리 및 읽기 성능을 제공하는 관계형 데이터베이스를 사용할 수 있습니다.
  • 마이크로 서비스를 사용하는 경우 데이터 스토리지를 포함하여 느슨하게 결합된 상태로 유지합니다. 구체화된 뷰는 서비스의 데이터를 통합하는 데 도움이 될 수 있습니다. 구체화된 뷰가 마이크로 서비스 아키텍처 또는 특정 시나리오에서 적절하지 않은 경우 DDD(도메인 기반 디자인) 에 맞게 잘 정의된 경계를 사용하고 요청 시 데이터를 집계하는 것이 좋습니다.

이 패턴은 다음과 같은 경우에 적합하지 않을 수 있습니다.

  • 원본 데이터가 단순하고 쿼리하기 용이한 경우
  • 원본 데이터는 매우 빠르게 변경되거나 보기를 사용하지 않고 액세스할 수 있습니다. 이러한 경우 뷰를 만드는 처리 오버헤드를 방지합니다.
  • 일관성은 높은 우선 순위입니다. 뷰는 원본 데이터와 완벽하게 일치하지 않을 수 있습니다.

워크로드 디자인

설계자는 워크로드 디자인에서 구체화된 뷰 패턴을 사용하여 Azure Well-Architected Framework 핵심 요소에서 다루는 목표와 원칙을 해결하는 방법을 평가해야 합니다. 다음은 그 예입니다.

핵심 요소 이 패턴으로 핵심 목표를 지원하는 방법
성능 효율성은 크기 조정, 데이터 및 코드의 최적화를 통해 워크로드가 수요를 효율적으로 충족 하는 데 도움이 됩니다. 구체화된 뷰는 데이터베이스 엔진 또는 클라이언트가 모든 요청에 대해 다시 계산할 필요 없이 복잡한 계산 또는 쿼리의 결과를 저장합니다. 이 디자인은 전체 리소스 소비를 줄입니다.

- PE:08 데이터 성능

이 패턴이 하나의 기둥 내에서 절충을 도입하는 경우, 이를 다른 기둥의 목표와 비교해서 고려해 보세요.

Example

Azure Table Storage에 Order, OrderItem 및 Customer 엔터티를 저장하는 판매 애플리케이션을 생각해 보겠습니다. 주문은 고객 ID, 주문 ID별 주문 항목 및 지역별 고객별로 분할됩니다. 이러한 키는 애플리케이션의 운영 액세스 패턴을 지원하지만 제품별로 그룹화된 판매 보고서는 파티션 간에 데이터를 읽고 애플리케이션 코드에서 결합해야 합니다.

다음 그림에서는 전자 제품 범주의 각 제품에 대한 총 판매 가치 및 고유 구매 고객 수를 저장하는 구체화된 뷰를 보여 줍니다. 원본 행 및 요약 값은 표시된 합계에 대한 전체 입력 데이터 세트가 아니라 설명입니다.

제품 범주별로 분할된 구체화된 판매 요약으로 결합된 Order, OrderItem 및 Customer 테이블을 보여 주는 다이어그램

백그라운드 프로세스는 필요한 원본 엔터티를 읽고 주문 항목을 주문 및 고객과 연결하며 제품별로 판매를 집계합니다. 고객에게 여러 주문이나 주문 항목이 있더라도, 제품별로 각 고객은 한 번만 집계합니다. 이 프로세스는 제품 범주 PartitionKey 와 제품 ID RowKey가 같은 별도의 요약 테이블에 결과를 씁니다. 이 요약 테이블은 데이터베이스 네이티브 구체화된 뷰가 아니라 애플리케이션에서 유지 관리되는 프로젝션입니다.

대시보드는 모든 요청에 대해 파티션 간 읽기 및 집계를 반복하는 대신 Electronics 파티션을 쿼리할 수 있습니다. 한 제품에 대한 조회는 두 키를 모두 제공합니다. 이러한 키의 쿼리 성능에 미치는 영향은 쿼리를 위한 디자인을 참조하세요.

보고서의 허용되는 최신성 유지 범위에 맞는 일정에 따라 요약을 새로 고침합니다. 게시하기 전에 새 버전을 빌드하고 유효성을 검사하므로 판독기는 다시 빌드하는 동안 이전 전체 버전을 계속 사용합니다. 새로 고침은 여전히 파티션 간 읽기 및 집계 비용이 발생하지만 반복된 보고서 쿼리는 결과를 다시 사용합니다. 원본 변경 내용은 후속 새로 고침에 포함할 때까지 표시되지 않습니다.

다음 단계

  • 인덱싱된 뷰 만들기 는 SQL 데이터베이스가 뷰에 인덱스를 만들어 계산된 뷰 결과를 유지하는 방법을 설명합니다.
  • NoSQL Azure Cosmos DB 변경 피드 디자인 패턴은 변경 피드 소비자가 구체화된 보기를 유지할 수 있는 방법을 설명합니다.
  • 구체화된 뷰 개요는 Azure Data Explorer 구체화된 뷰에 대해 설명합니다.
  • Azure Managed Redis는 사전 계산된 쿼리 결과를 영구 데이터 저장소 앞에서 읽기 최적화 계층으로 캐시할 수 있습니다.
  • Azure Table Storage 애플리케이션 논리 또는 백그라운드 프로세스에서 생성된 미리 계산된 뷰 데이터를 저장할 수 있습니다.

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

  • CQRS(명령 및 쿼리 책임 분리 패턴). 기본 데이터 값이 변경될 때 발생하는 이벤트에 응답하여 구체화된 뷰에서 정보를 업데이트하는 데 사용합니다.
  • 이벤트 소싱 패턴 CQRS 패턴과 함께 사용하여 구체화된 뷰에서 정보를 유지 관리합니다. 구체화된 뷰의 데이터 값이 변경 내용을 기반으로 하는 경우 시스템은 이러한 변경 내용을 설명하는 이벤트를 발생시키고 이벤트 저장소에 저장할 수 있습니다.
  • 인덱스 테이블 패턴입니다. 보통 구체화된 뷰의 데이터는 기본 키로 구성되지만, 쿼리는 다른 필드의 데이터를 검사해 구체화된 뷰에서 정보를 검색할 필요가 있습니다. 이 패턴을 사용하여 네이티브 보조 인덱스를 지원하지 않는 데이터 저장소에 대한 데이터 집합을 통해 보조 인덱스를 만듭니다.