집계에 인덱싱 된 뷰 사용-너무 좋지 않습니까?


28

우리는 상당히 많은 레코드 수 (10 ~ 2 천만 행)를 가진 데이터웨어 하우스를 가지고 있으며 특정 날짜 사이의 레코드를 계산하거나 특정 플래그로 레코드를 계산하는 쿼리를 실행하는 경우가 있습니다.

SELECT
    f.IsFoo,
    COUNT(*) AS WidgetCount
FROM Widgets AS w
JOIN Flags AS f
    ON f.FlagId = w.FlagId
WHERE w.Date >= @startDate
GROUP BY f.IsFoo

성능은 좋지 않지만 상대적으로 느려질 수 있습니다 (콜드 캐시에서 10 초 정도).

최근 GROUP BY에 인덱싱 된 뷰에서 사용할 수 있음을 발견 하고 다음과 비슷한 것을 시도했습니다.

CREATE VIEW TestView
WITH SCHEMABINDING
AS
    SELECT
        Date,
        FlagId,
        COUNT_BIG(*) AS WidgetCount
    FROM Widgets
    GROUP BY Date, FlagId;
GO

CREATE UNIQUE CLUSTERED INDEX PK_TestView ON TestView
(
    Date,
    FlagId
);

결과적으로 첫 번째 쿼리의 성능은 이제 <100ms이고 결과 뷰 및 인덱스는 <100k입니다 (행 수는 크지 만 날짜 및 플래그 ID 범위는이 뷰에 1000-2000 개의 행만 포함됨).

아마도 이것이 위젯 테이블에 대한 쓰기 성능을 저하시킬 수 있다고 생각했지만 아니오-이 테이블에 대한 삽입 및 업데이트 성능은 내가 알 수있는 한 거의 영향을받지 않습니다 (또한이 테이블은 데이터웨어 하우스이므로 드물게 업데이트됩니다) 어쨌든)

나에게 이것은 사실 이기에는 너무 좋은 것 같습니다. 이 방법으로 인덱싱 된 뷰를 사용할 때주의해야 할 사항은 무엇입니까?


2
실제로 유효한 SQL이되도록 스크립트를 다시 작성할 수 있습니까? 내가 당신의 대본 이라고 생각하기 때문에 당신 SELECTCREATE VIEW대본이 잘못되었습니다 CREATE INDEX.
Mark Sinkinson

2
@MarkSinkinson 사과, 가상 테이블에 유효한 SQL을 작성하는 것은 어렵다는 사실이 밝혀졌습니다.
Justin

MAX에 대한 고급 뷰, 자체 또는 외부 조인을 포함하거나 다른 뷰를 참조하는 뷰 인덱싱과 같은 고급 뷰를 원할 때 '실제로 너무 좋았습니다'는 SQL Server의 모든 뷰가 아닙니다. docs.microsoft.com/en-us/sql/relational-databases/views/…를 허용 했습니다 . 그래서 나는 항상 지나치게 야심을 가지고 일을 축소해야합니다. 그러나 더 간단한 집계에서는 정말 훌륭합니다. 심지어 SUM도 지원됩니다.
Simon_Weaver

답변:


29

앞에서 언급했듯이 뷰 자체는 적은 수의 행만 구체화하므로 전체 테이블 을 업데이트하더라도 뷰 업데이트와 관련된 추가 I / O는 무시할 수 있습니다. 뷰를 만들 때 느끼는 가장 큰 고통을 이미 느꼈을 것입니다. 다음으로 가장 가까운 것은 뷰에서 새 행이 필요한 여러 개의 새로운 ID로 기본 테이블에 gazillion 행을 추가하는 것입니다.

이것은 사실이 너무 좋지 않습니다. 인덱싱 된 뷰를 사용하려는 방식이나 가장 효과적인 방법 중 하나 인 쓰기 시점에서 향후 쿼리 집계 비용을 지불하는 인덱싱 된 뷰를 사용하고 있습니다. 이는 결과가 소스보다 훨씬 작을 때와 기본 데이터가 업데이트되는 것보다 집계가 더 자주 요청 될 때 (일반적으로 OLTP보다 DW에서 더 일반적 일 때) 가장 효과적입니다.

불행히도 많은 사람들은 뷰 인덱싱이 마술이라고 생각합니다. 인덱스는 모든 뷰, 특히 테이블을 조인하거나 소스와 같은 수의 행을 생성하는 뷰 (또는 곱하기)를 더 효율적으로 만들지는 않습니다. 이 경우 뷰의 I / O는 원래 쿼리와 동일하거나 더 나쁩니다. 동일한 행이 많을뿐만 아니라 더 많은 열을 저장하고 구체화하기도합니다. 따라서 SSD를 사용하더라도 I / O, 네트워크 및 클라이언트 처리 / 렌더링은 여전히 ​​큰 결과 집합을 클라이언트에 반환하는 데 여전히 주요 병목 현상이 남아 있기 때문에 사전에 구체화하면 아무런 이점이 없습니다. 런타임에 조인을 피함으로써 절약되는 비용은 여전히 ​​사용중인 다른 모든 리소스와 비교하여 측정 할 수 없습니다.

비 클러스터형 인덱스와 같이 지나치게 과도하게 사용하지 않도록주의하십시오. 하나의 테이블에 10 개의 서로 다른 인덱싱 된 뷰를 추가하면 특히 그룹화 열이 클러스터링 키에없는 경우 작업 부하의 쓰기 부분에 더 많은 영향을 미칩니다.

어이, 나는이 주제에 대해 블로그를하고 싶었습니다.


19

아론의 대답은이 질문을 잘 다루었습니다. 추가해야 할 두 가지 :

  1. 집계 인덱싱 된 뷰는 행 간 경합 및 교착 상태로 이어질 수 있습니다. 일반적으로 두 개의 인서트는 교착 상태가 아닙니다 (잠금 에스컬레이션 또는 잠금 해시 충돌과 같은 드문 상황 제외). 그러나 두 인서트가 뷰에서 동일한 그룹을 처리하면 경쟁합니다. 같은 점은 잠금 (DML, 잠금 힌트)을 취하는 다른 것을 나타냅니다.
  2. 집계되지 않은 인덱싱 된 뷰도 유용 할 수 있습니다. 여러 테이블의 열을 인덱싱 할 수 있습니다. 이렇게하면 하나의 테이블을 효율적으로 필터링하고 조인 된 테이블의 열을 기준으로 정렬 할 수 있습니다. 이 패턴은 전체 테이블 조인을 작은 상수 시간 쿼리로 변환 할 수 있습니다.

집계 및 조인 뷰를 모두 큰 이점으로 사용했습니다.

모든 유스 케이스에서 완벽한 케이스처럼 보입니다. 인덱싱 된 뷰는 활용도가 매우 낮은 기술입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.