Странный сбой экземпляра SQL Server при приведении к числовому

20

Во время работы с 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 2008 R2 на 32-разрядной Windows Server 2003.

Это известная ошибка? Есть ли патч для SQL Server?

SteLoe
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Пол Уайт говорит, что GoFundMonica

Ответы:

20

Мне удалось воспроизвести на 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 строки. Я понятия не имею, как это получено из показанной гистограммы.

Мартин Смит
источник