Byłem w stanie zreperować na 2008 R1 SP3 10.00.5512, ale zainstalowałem najnowszą CU (14).
Przeglądając błędy naprawione w interweniujących wersjach, wygląda na to, że musisz uaktualnić do wersji zawierającej następującą poprawkę.
Naruszenie zasad dostępu po uruchomieniu zapytania zawierającego wiele stałych wartości w klauzuli IN w SQL Server 2008 lub SQL Server 2012
W 2008 R2 potrzebujesz co najmniej 9 CU dla SP1 lub CU 5 dla SP2.
Opis objawów jest dość krótki, ale wspomina o niedopasowanych typach danych
Po uruchomieniu zapytania zawierającego wiele stałych wartości w klauzuli IN w Microsoft SQL Server 2008, Microsoft SQL Server 2012 lub Microsoft SQL Server 2008 R2 może wystąpić naruszenie zasad dostępu.
Uwaga Aby problem mógł wystąpić, stałe w klauzuli IN nie mogą być dokładnie zgodne z typem danych kolumny.
Nie definiuje „wielu”. Z testów, które zrobiłem, podejrzewam, że może to oznaczać „20 lub więcej”, ponieważ wydaje się, że jest to punkt odcięcia między dwiema różnymi metodami szacowania liczności.
Katastrofa miała miejsce w ramach kilku metod wywoływanych przy CScaOp_In::FCalcSelectivity()
użyciu nazw takich jak LoadHistogramFromXVariantArray()
i CInMemHistogram::FJoin() -> WalkHistograms()
.
W przypadku 19 lub mniej różnych pozycji na liście metody te w ogóle nie były wywoływane. Podobny SQL Sever 2000 bug wspomina również ten punkt odcięcia jako znaczące.
Wypełnianie tabeli testowej 100 000 wierszy losowych danych testowych wartościami od 0 do 1047 i histogramem rozpoczynającym się w następujący sposób
+--------------+------------+---------+---------------------+----------------+
| 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 |
+--------------+------------+---------+---------------------+----------------+
Zapytanie
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)
Pokazuje szacunkowe wiersze z 1856 r.
Jest to dokładnie to, czego można się spodziewać po uzyskaniu szacunkowych wierszy dla 19 predykatów równości indywidualnie i zsumowaniu ich.
+-------+----------------+-------+
| 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
Formuła przestaje działać, gdy 20
zostanie dodana do listy w ( wygenerowane zostaną szacunkowe wiersze, 1902.75
a nie 1952
dodanie tego 96
do sumy).
BETWEEN
wydaje się używać jeszcze jednej metody obliczania szacunków liczności.
where mpnr BETWEEN 1 AND 20
szacuje tylko 1829,6 wierszy. Nie mam pojęcia, jak to wynika z pokazanego histogramu.