我能够跟踪到这个陈述:
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.
解决方法
查看介入版本中修复的错误,看起来好像需要升级到包含以下修复的构建.
在2008 R2上,您至少需要CU 9 for SP1或CU 5 for SP2.
症状的描述有些简短,但提到了不匹配的数据类型
When you run a query that contains many constant values in an IN@H_301_17@ clause in Microsoft sql Server 2008,Microsoft sql Server 2012 or in@H_301_17@ Microsoft sql Server 2008 R2,an access violation might occur.
Note For the issue to occur,the constants in the IN clause cannot@H_301_17@ match exactly with the column data type.
它没有定义“很多”.从我做的测试中我怀疑这可能意味着“20或更多”,因为这似乎是两种估算基数的不同方法之间的截止点.
崩溃发生在CScaOp_In :: FCalcSelectivity()调用的几个方法中,其名称如LoadHistogramFromXVariantArray()和CInMemHistogram :: FJoin() – > WalkHistograms().
对于19个或更少的不同列表项,这些方法根本没有被调用. A similar SQL Sever 2000 bug也提到这个截止点是重要的.
使用值为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而不是1952年,将生成另外96个将生成).
BETWEEN似乎还在使用另一种计算基数估算的方法.
其中mpnr BETWEEN 1和20估计只有1829.6行.我不知道这是如何从显示的直方图得出的.