2009-09-25 9 views
5

많은 테이블 (10-11)에 조인하는 상당히 복잡한 저장 프로 시저를 디버깅하려고합니다. 나는 트리의 일부분에 대해 예상되는 행 수가 실제 행 수와 크게 다르다는 것을 알게되었다. 최악의 SQL 서버는 실제 행 수가 55,000 행이 반환 될 때 1 행이 반환 될 것이라고 추정한다!SQL 서버는 예상 행 수를 어떻게 산출합니까?

필자는 왜 모든 통계가 최신인지를 알아 내려고 노력하고 있으며 여러 테이블에서 FULLSCAN으로 통계를 업데이트했습니다. 사용자 정의 함수 나 테이블 변수를 사용하지 않습니다. 늘어나는만큼 SQL 서버가 얼마나 많은 행이 반환 될지 정확하게 예측할 수 있어야하지만, 수만 개의 RDI 조회를 수행하는 계획을 계속 선택합니다 (1 개만 수행 할 것으로 예상되는 경우). 또는 2).

추정 행 수가 너무 많은 이유를 이해하고 시도하려면 어떻게해야합니까?

UPDATE : 그래서 suspicous 보인다 나는 특히 하나 개의 노드를 찾은 계획보고 - 그 테이블은 다음 predecate 사용하여 테이블에 스캔 :

status <> 5 
AND [type] = 1 
OR [type] = 2 

이 술어는 전체 테이블을 반환합니다 (630 개의 행 - 테이블 자체는 성능이 좋지 않은 원본을 스캔합니다.) 그러나 SQL Server는 예상되는 행 수가 37에 불과합니다. SQL 서버는 이와 함께 여러 중첩 루프를 수행하여 RDI 조회, 인덱스 스캔 및 색인을 수행합니다 찾는다. 이것이 내 거대한 계산 착오의 원천이 될 수 있을까? 더 현명한 행 수를 계산하려면 어떻게해야합니까? 이미 통계를 업데이트하기 때문에

+0

당신이 당신의 테이블 정의를 게시하시기 바랍니다 수와 전체 쿼리를 해결할 수 있습니다 귀하의 인덱스를 다시? – Quassnoi

+0

죄송합니다. 실제로는 아니지만 - 너무 커서 (250 행 sp + 10 테이블). – Justin

+3

당신의 술어가 정확히 (괄호가없는) 그런 경우 논리 문제가있을 수 있습니다. AND는 OR보다 우선합니다. [상태] <> 5 AND (유형 = 1 또는 유형 2) – GilaMonster

답변

8

SQL Server 스플릿 (here)에서 다음 데이터까지 200 범위로 각 인덱스 :

  • RANGE_HI_KEY

    히스토그램 단계의 상단 경계를 나타내는 키 값.

  • RANGE_ROWS

    많은 행이 범위 안에있는 방법을 지정합니다 (그들은 RANGE_HI_KEY 이전보다 작은이 RANGE_HI_KEY보다 작은, 그러나 더 크다).

  • EQ_ROWS

    많은 행이 RANGE_HI_KEY 정확히 동일한 방법을 지정합니다. 범위 안에서 고유 값 당 행

  • AVG_RANGE_ROWS

    평균 수.

  • DISTINCT_RANGE_ROWS

    는 고유 키 값 (RANGE_HI_KEYRANGE_HI_KEY 자체 전에 이전 키를 포함하지 않음)이 범위 안에 얼마나 많은 지정합니다

은 일반적으로 가장 인구 값은 RANGE_HI_KEY로 이동합니다.

그러나 범위에 들어갈 수 있으며 배포시 왜곡이 발생할 수 있습니다.

(다른 사람 사이)이 데이터를 상상해 : 행의

키 값 카운트

1   1 
2   1 
3   10000 
4   1 

SQL Server은 일반적으로 두 개의 범위 빌드 : 1 이러한 통계를 만드는 다음 인구 값에 34로를 :

RANGE_HI_KEY RANGE_ROWS EQ_ROWS AVG_RANGE_ROWS DISTINCT_RANGE_ROWS 
3    2   10000 1    2 

예 : 2이면 1 행이 있으므로 인덱스 액세스를 사용하는 것이 좋습니다. 3의 범위 내에서 이동하는 경우

그러나, 통계는 다음과 같습니다

RANGE_HI_KEY RANGE_ROWS EQ_ROWS AVG_RANGE_ROWS DISTINCT_RANGE_ROWS 
4    10002  1  3334   3 

최적화가 키 2에 대한 3334 행은 인덱스 액세스가 너무 비싸 생각한다.

+0

전체 스캔 통계를 업데이트해도 문제를 해결할 수 없으면 어떻게 해결할 수 있습니까? – Meysam

+0

@Maysam : 자주 사용하는 술어에'CREATE STATISTICS'를 사용할 수 있습니다. – Quassnoi

0

, 나는 스니핑 모든 매개 변수를 제거하기 위해 노력하겠다고 : 그것은 각 인덱스에 대해 유지하는 통계를 사용

CREATE PROCEDURE xyz 
(
    @param1 int 
    ,@param2 varchar(10) 

)AS 

DECLARE @param_1 int 
     ,@param_2 varchar(10) 

SELECT @[email protected] 
     ,@[email protected] 

...complex query here.... 
...WHERE [email protected]_1 AND [email protected]_2.... 

go 
3

.

는 데이터베이스 (경고의 모든 테이블에 대한 모든 통계를 업데이트하려면 (당신은 또한 비 인덱스 컬럼에 대한 통계를 생성 할 수 있습니다). 매우 큰 데이터베이스에 시간이 좀 걸릴 것이 작업을 수행하지 마십시오 당신의 DBA와 확인하지 않고 생산 서버에 ...) : 당신이 당신의 가장 활발한 인덱스 (삽입 또는 DELETES의 예를 많이 재건 정기적으로 예약 된 작업을)이없는 경우

exec sp_msforeachtable 'UPDATE STATISTICS ?' 

, 당신은 다시 작성해야합니다 당신의 색인 (위의 동일한주의 사항이 적용됨) :

exec sp_msforeachtable "DBCC DBREINDEX('?')" 
관련 문제