Мне удалось воспроизвести на 2008 R1 SP3 10.00.5512, но установка последней CU (14) исправила это.
Изучая ошибки, исправленные в промежуточных версиях, кажется, что вам нужно обновить систему до сборки, включающей следующее исправление.
Нарушение доступа при запуске запроса, который содержит много постоянных значений в предложении IN в SQL Server 2008 или в SQL Server 2012
Поскольку вы находитесь на 2008 R2, вам понадобится как минимум 9 д.е. для SP1 или 5 д.е. для SP2.
Описание симптомов несколько кратко, но упоминает несоответствующие типы данных
При выполнении запроса, который содержит много постоянных значений в предложении IN в Microsoft SQL Server 2008, Microsoft SQL Server 2012 или Microsoft SQL Server 2008 R2, может произойти нарушение доступа.
Примечание. Для возникновения проблемы константы в предложении IN не могут точно соответствовать типу данных столбца.
Это не определяет «много». Я подозреваю, что по результатам тестирования это может означать «20 или более», поскольку это, по-видимому, точка отсечения между двумя различными методами оценки мощности.
Сбой происходил внутри пары методов, вызванных CScaOp_In::FCalcSelectivity()
с именами, такими как LoadHistogramFromXVariantArray()
и CInMemHistogram::FJoin() -> WalkHistograms()
.
Для 19 или менее отдельных элементов списка эти методы вообще не вызывались. Аналогичный SQL Sever 2000 ошибка также упоминает об этом срезанных точках как значительные.
Заполнение тестовой таблицы 100 000 строк случайных тестовых данных значениями от 0 до 1047 и гистограммой, начинающейся следующим образом
+--------------+------------+---------+---------------------+----------------+
| 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
добавления в список «in» ( сгенерированные строки, 1902.75
а не сгенерированные при 1952
добавлении еще одного 96
к итогу).
BETWEEN
кажется, использует еще один метод расчета оценок мощности.
where mpnr BETWEEN 1 AND 20
оценивает только 1829,6 строки. Я понятия не имею, как это получено из показанной гистограммы.