sql-server – 在转换为数字时,奇怪的SQL Server实例崩溃

前端之家收集整理的这篇文章主要介绍了sql-server – 在转换为数字时,奇怪的SQL Server实例崩溃前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在使用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版本是Windows Server 2003 32位上的2008 R2.

这是一个已知的错误
是否有sql Server补丁?

解决方法

我能够在2008 R1 SP3 10.00.5512上重新编译,但安装了最新的CU(14)修复了它.

查看介入版本中修复的错误,看起来好像需要升级到包含以下修复的构建.

Access violation when you run a query that contains many constant values in an IN clause in SQL Server 2008 or in SQL Server 2012

在2008 R2上,您至少需要CU 9 for SP1或CU 5 for SP2.

症状的描述有些简短,但提到了不匹配的数据类型

When you run a query that contains many constant values in an IN
clause in Microsoft sql Server 2008,Microsoft sql Server 2012 or in
Microsoft sql Server 2008 R2,an access violation might occur.

Note For the issue to occur,the constants in the IN clause cannot
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行.我不知道这是如何从显示的直方图得出的.

猜你在找的MsSQL相关文章