Pude repro en 2008 R1 SP3 10.00.5512 pero la instalación de la última CU (14) lo arregló.
Al revisar los errores corregidos en las versiones intermedias, parece que necesita actualizar a una compilación que incluye la siguiente corrección.
Infracción de acceso cuando ejecuta una consulta que contiene muchos valores constantes en una cláusula IN en SQL Server 2008 o en SQL Server 2012
Como está en 2008 R2, necesitará al menos 9 u.m. para SP1 o 5 u.m. para SP2.
La descripción de los síntomas es algo breve pero menciona tipos de datos no coincidentes
Cuando ejecuta una consulta que contiene muchos valores constantes en una cláusula IN en Microsoft SQL Server 2008, Microsoft SQL Server 2012 o en Microsoft SQL Server 2008 R2, puede producirse una infracción de acceso.
Nota Para que se produzca el problema, las constantes en la cláusula IN no pueden coincidir exactamente con el tipo de datos de la columna.
No define "muchos". Según las pruebas que hice, sospecho que esto puede significar "20 o más", ya que este parece ser el punto de corte entre dos métodos diferentes para estimar la cardinalidad.
El bloqueo estaba ocurriendo dentro de un par de métodos llamados CScaOp_In::FCalcSelectivity()
con nombres como LoadHistogramFromXVariantArray()
y CInMemHistogram::FJoin() -> WalkHistograms()
.
Para 19 o menos elementos distintos en la lista, estos métodos no fueron llamados en absoluto. Un error similar de SQL Sever 2000 también menciona este punto de corte como significativo.
Rellenar una tabla de prueba con 100,000 filas de datos de prueba aleatorios con valores entre 0 y 1047 y un histograma que comienza de la siguiente manera
+--------------+------------+---------+---------------------+----------------+
| 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 |
+--------------+------------+---------+---------------------+----------------+
La consulta
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)
Muestra filas estimadas de 1856.
Esto es exactamente lo que se esperaría al obtener las filas estimadas para los 19 predicados de igualdad individualmente y sumarlos.
+-------+----------------+-------+
| 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
La fórmula ya no funciona después de 20
agregarla a la lista de entrada (filas estimadas en 1902.75
lugar de la 1952
que 96
generaría agregar otra al total).
BETWEEN
parece utilizar otro método para calcular las estimaciones de cardinalidad.
where mpnr BETWEEN 1 AND 20
estima solo 1829.6 filas. No tengo idea de cómo se deriva eso del histograma que se muestra.