숫자로 캐스트 할 때 이상한 SQL Server 인스턴스 충돌 Server 인스턴스가

C # Entity Framework로 작업하는 동안 SQL Server 인스턴스가 충돌하는 것을 발견했습니다.

나는이 진술을 추적 할 수있었습니다.

SELECT * FROM dbo.[TestTable]
where mpnr in (1099059904,
1038139906,
1048119902,
1045119902,
1002109903,
1117109910,
1111149902,
1063149902,
1117159902,
1116109904,
1105079905,
1012079906,
1129129904,
1103059905,
1065059905,
1091059906,
1110149904,
1129149903,
1083029905,
1080139904,
1076109903,
1010019902,
1058019902,
1060019903,
1053019902,
1030089902,
1018149902,
1077149902,
1010109901,
1011109901,
1000119902,
1023049903,
1107119909,
1108119909,
1106119909)

테이블은 다음과 같습니다.

CREATE TABLE dbo.[TestTable]([MPNR] [numeric](9, 0) NOT NULL)

쿼리를 시작할 때마다 충돌이 발생합니다. IN절 내의 값 수를 줄이면 작동합니다. (물론 행을 반환하지 않습니다.)

IN절의 값 은 10 자리 숫자이며 열에는 9 자리 만 있지만 SQL Server 인스턴스 전체가 충돌하지 않아야합니다.

내 SQL Server 버전은 Windows Server 2003 32 비트에서 2008 R2입니다.

알려진 버그입니까? SQL Server 용 패치가 있습니까?



답변

2008 R1 SP3 10.00.5512에서 재현 할 수 있었지만 최신 CU (14)를 설치하면 문제가 해결되었습니다.

중간 버전에서 수정 된 버그를 검토하면 다음 수정 사항이 포함 된 빌드로 업그레이드해야하는 것처럼 보입니다.

SQL Server 2008 또는 SQL Server 2012의 IN 절에 많은 상수 값이 포함 된 쿼리를 실행할 때 액세스 위반

2008 R2를 사용하는 경우 SP1의 경우 CU 9 이상, SP2의 경우 CU 5 이상이 필요합니다.

증상에 대한 설명이 다소 간단하지만 일치하지 않는 데이터 유형이 언급 됨

Microsoft SQL Server 2008, Microsoft SQL Server 2012 또는 Microsoft SQL Server 2008 R2의 IN 절에 많은 상수 값이 포함 된 쿼리를 실행하면 액세스 위반이 발생할 수 있습니다.

참고 문제가 발생하기 위해 IN 절의 상수는 열 데이터 형식과 정확히 일치 할 수 없습니다.

“많은”을 정의하지 않습니다. 테스트에서 나는 이것이 카디널리티를 추정하는 두 가지 다른 방법 사이의 컷오프 포인트 인 것처럼 보이기 때문에 이것이 “20 이상”을 의미한다고 생각합니다.

충돌이 호출 방법 중 몇 가지 내부에 무슨 일이 일어 CScaOp_In::FCalcSelectivity()등의 이름으로 LoadHistogramFromXVariantArray()CInMemHistogram::FJoin() -> WalkHistograms().

목록 항목이 19 개 이하인 경우이 메서드는 전혀 호출되지 않았습니다. 유사한 SQL 끊다 2000 버그는 상당한로 포인트 떨어져,이 컷을 언급하고있다.

0에서 1047 사이의 값을 가진 100,000 개의 행으로 구성된 임의의 테스트 데이터와 다음과 같이 시작하는 히스토그램으로 테스트 테이블 채우기

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            0 |          0 |     104 |                   0 | 1              |
|            8 |        672 |     118 |                   7 | 96             |
|           13 |        350 |     118 |                   4 | 87.5           |
|           18 |        395 |     107 |                   4 | 98.75          |
|           23 |        384 |      86 |                   4 | 96             |
|           28 |        371 |      85 |                   4 | 92.75          |
+--------------+------------+---------+---------------------+----------------+

쿼리

SELECT * FROM dbo.[TestTable]
where mpnr in (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19)
option (maxdop 1)

1856 년 예상 행을 표시합니다.

이것은 19 개의 등식 술어에 대한 예상 행을 개별적으로 가져와 함께 더하면 예상됩니다.

+-------+----------------+-------+
| 1-7   | AVG_RANGE_ROWS | 96    |
| 8     | EQ_ROWS        | 118   |
| 9-12  | AVG_RANGE_ROWS | 87.5  |
| 13    | EQ_ROWS        | 118   |
| 14-17 | AVG_RANGE_ROWS | 98.75 |
| 18    | EQ_ROWS        | 107   |
| 19    | AVG_RANGE_ROWS | 96    |
+-------+----------------+-------+

7*96 + 118 + 4*87.5 + 118 + 4*98.75 + 107 + 1*96 = 1856

공식이 더 이상 20목록에 추가 된 후에 는 공식이 작동하지 않습니다 ( 총계에 다른 것을 추가하는 1902.75것이 아니라 예상 행 ).195296

BETWEEN 카디널리티 추정값을 계산하는 또 다른 방법을 사용하는 것 같습니다.

where mpnr BETWEEN 1 AND 201829.6 개의 행만 추정합니다. 나는 이것이 표시된 히스토그램에서 어떻게 파생되는지 전혀 모른다.