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.

这是一个已知的错误?@H_301_17@是否有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@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行.我不知道这是如何从显示的直方图得出的.

猜你在找的MsSQL相关文章