이 분할 된 뷰에서 최적화 프로그램이 관련없는 테이블을 제거하도록 할 수 있습니까?


22

큰 테이블에 대해 서로 다른 아키텍처를 테스트하고 있는데 한 가지 제안은 분할 된 뷰를 사용하여 큰 테이블을 일련의 작은 "파티셔닝 된"테이블로 나누는 것입니다.

1 , 2 , 3 , 4

이 접근법을 테스트하면서, 나는 나에게 전혀 이해가되지 않는 것을 발견했습니다. 팩트 뷰에서 "파티션 열"을 필터링하면 옵티마이 저는 관련 테이블에서만 검색합니다. 또한 차원 테이블에서 해당 열을 필터링하면 옵티마이 저가 불필요한 테이블을 제거합니다.

그러나 차원의 다른 측면을 필터링하면 옵티마이 저가 각 기본 테이블의 PK / CI를 찾습니다.

문제의 쿼리는 다음과 같습니다.

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where o.ObservationDateKey >= 20000101
    and o.ObservationDateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.DateKey >= 20000101
    and od.DateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.[Year] >= 2000 and od.[Year] < 2006
group by od.[Year];

키의 사실 필터

키의 희미한 필터

화면의 희미한 필터

다음 은 SQL Sentry Plan Explorer 세션에 대한 링크 입니다.

실제로 더 큰 테이블을 분할하여 비슷한 방식으로 파티션 제거가 응답하는지 확인하려고합니다.

차원의 측면을 필터링하는 (간단한) 쿼리에 대한 파티션 제거를 얻습니다.

그 동안 다음은 통계 전용 데이터베이스 사본입니다.

https://gist.github.com/swasheck/9a22bf8a580995d3b2aa

"이전"카디널리티 추정기는 비용이 덜 드는 계획을 얻지 만 이는 (필요하지 않은) 각 인덱스 탐색에 대한 카디널리티 추정치가 낮기 때문입니다.

차원의 다른 측면으로 필터링 할 때 키 열을 사용하여 옵티마이 저가 관련없는 테이블에 대한 탐색을 제거 할 수있는 방법이 있는지 알고 싶습니다.

SQL Server 버전 :

Microsoft SQL Server 2014 - 12.0.2000.8 (X64) 
    Feb 20 2014 20:04:26 
    Copyright (c) Microsoft Corporation
    Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)

참고로 .. 마지막 통계 스트림이 손상되었습니다CREATE STATISTICS [_WA_Sys_00000008_2FCF1A8A] ON [dbo].[Observation_2010]([StationStateCode]) WITH STATS_STREAM = 0x01000000010000000000000000000000D4531EDB00000000D5080000000000009508000000000000AF030000AF000000020000000000000008D000340000000007000000E65DE0007DA5000076F9780000000000867704000000000000000000ABAAAA3C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Kin Shah

통계 전용 데이터베이스의 스크립트가 잘린 것처럼 보입니다. "전체 파일보기"를 클릭하고 zip 파일을 다운로드하려고했지만 어느 쪽이든 ObservationDates테이블에 대한 통계가 없습니다 . 나는 4199의 경우에도 바울과 같은 계획을 얻지 못하고 있으며 이것이 바로 그 이유라고 생각합니다.
Geoff Patterson

@GeoffPatterson 그것은 나를 위해 작동합니다. 원시 파일에 대한 링크를 클릭 했습니까? gist.githubusercontent.com/swasheck/9a22bf8a580995d3b2aa/raw/... 킨이 언급 한 바와 같이 그러나, 마지막 통계 스트림이 손상되었습니다 : /
swasheck

원시 파일의 링크를 클릭했습니다. 이 스크립트는 작동하지만 (Kin에서 언급 한 문제 제외)에 대한 통계를 생성하는 로직이 없습니다 ObservationDates. UPDATE STATISTICS ObservationDates WITH ROWCOUNT = 10000Paul이 보여준 계획을 얻기 위해 수동으로 실행했습니다 .
Geoff Patterson

이상한. 새 데이터베이스를 만들고 해당 스크립트를 실행하면 통계 개체가 있습니다 (물론 인덱스입니다). ObservationDates그래서 무슨 일이 일어나고 있는지 잘 모르겠습니다. 또한, 나는 계획 폴을 생성 할 수 없습니다. 나는 업데이트를 시도 할 것이다.
swasheck

답변:


10

추적 플래그 4199를 사용하십시오.

나는 또한 발행해야했다 :

UPDATE STATISTICS dbo.ObservationDates 
WITH ROWCOUNT = 73049;

아래 표시된 계획을 얻으십시오. 이 테이블에 대한 통계가 업로드에서 누락되었습니다. 73,049 그림은 계획 탐색기 첨부의 테이블 카디널리티 정보에서 가져온 것입니다. SQL Server 2014 SP1 CU4 (빌드 12.0.4436)를 두 개의 논리 프로세서와 함께 사용했으며 최대 메모리는 2048MB로 설정했으며 4199 외에 추적 플래그는 없었습니다.

그런 다음 동적 파티션 제거 기능이있는 실행 계획을 얻어야합니다.

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where 
    od.[Year] >= 2000 and od.[Year] < 2006
group by 
    od.[Year]
option (querytraceon 4199);

조각 계획 :

조각 계획

이것은 나빠 보일 수 있지만 필터는 모두 시작 필터입니다. 술어의 예는 다음과 같습니다.

필터 속성

루프 반복마다 시작 술어가 테스트되며 true를 리턴하는 경우에만 아래의 클러스터 된 인덱스 찾기가 실행됩니다. 따라서 동적 파티션 제거.

이것은 아마도없는 매우 계획이 평행 특히, 정적 제거로 효율적입니다.

당신은 같은 힌트를 시도해야 할 수 있습니다 MAXDOP 1, FAST 1또는 FORCESEEK보기에 같은 계획을 얻을 수 있습니다. 분할 된 뷰 (예 : 분할 된 테이블)를 사용하는 옵티 마이저 비용 선택은 까다로울 수 있습니다.

요점은 분할 된 뷰로 동적 파티션을 제거하기 위해 시작 필터를 갖춘 계획이 필요하다는 것입니다.


USE PLAN힌트 가 포함 된 쿼리 : (ist.github.com을 통해) :


1
좋은 정보입니다, 폴 감사합니다! SQL Server가 이러한 유형의 제거를 수행 할 수있는 방법이없는 이유에 대한 답변을 작성한 후에 궁금했습니다. 거기에 나타났습니다, 나는 전에 본 적이 없었습니다!
Geoff Patterson

6

필자는 파티션 된 뷰에서 "테이블 제거"를 얻기 위해 쿼리에서 파티션 열의 값 (또는 값 범위)을 명시 적으로 지정해야한다는 것을 항상 관찰했습니다. 이는 SQL Server 2000에서 SQL Server 2014까지 프로덕션 환경에서 분할 된 뷰를 사용한 경험을 기반으로합니다.

SQL Server에는 엔진이 루프 외부의 행 값을 기반으로 루프 내부의 적절한 테이블을 직접 탐색 할 수있는 루프 조인 연산자 개념이 없습니다. 그러나 Paul의 답변에서 설명한 것처럼 시작 필터가있는 계획은 루프의 내부에서 관련이없는 테이블을 일정 시간에 동적으로 건너 뛸 수 있습니다 (실제 검색을 수행하는 로그와는 대조적 임).

그러나 파티션 된 테이블의 경우이 유형의 탐색 (특정 파티션에 대한)이 지원됩니다.

분할 된 뷰를 사용하도록 고정 된 경우 다른 옵션은 다음과 같은 쿼리를 여러 쿼리로 분할하는 것입니다.

-- Gather than the min/max values for the partition column
DECLARE @minDateKey INT,
        @maxDateKey INT
SELECT @minDateKey = MIN(DateKey),
        @maxDateKey = MAX(DateKey)
FROM dbo.ObservationDates od
WHERE od.[Year] >= 2000 and od.[Year] < 2006

-- Since I have a stats-only copy of the database, simulate having run the query above
-- (You can comment this out since you have the actual data.)
SELECT @minDateKey = 20000101, @maxDateKey = 20051231

-- Adjust the query to use the min/max values of the partition column
-- rather than filtering on a different column in the dimension table
select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
WHERE od.DateKey >= @minDateKey AND od.DateKey <= @maxDateKey
group by od.[Year]
-- Must use OPTION RECOMPILE; otherwise the plan will touch all tables because it
-- must do so in order to be valid for all values of the parameters!
OPTION (RECOMPILE)

이것은 다음과 같은 계획을 산출합니다. 이제 차원 테이블에 도달하는 추가 쿼리가 있지만 (아마도 훨씬 더 큰) 팩트 테이블에 대한 쿼리가 최적화되었습니다.

여기에 이미지 설명을 입력하십시오


변수에 의존하지 않고 첫 번째 쿼리를 두 번째 쿼리에 통합하면 동일한 효과를 얻을 수 있습니까?
Andriy M

@AndriyM 내가 당신을 올바르게 이해한다면, 대답은 아니오이며, 동일한 효과를 얻지 못하고 두 쿼리를 결합하려고하면 쿼리 계획이 파티션 된보기의 모든 테이블을 만질 것입니다. 그런 다음, 첫 번째 쿼리를 실행 값을 붙여한다면 20000101하고 20051231대신 변수 (또는 응용 프로그램에서 두 개의 쿼리를 통해 비슷한 할), 다음 네, 같은 효과는 변수를 사용하지 않고 달성 할 것입니다.
제프 패터슨
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.