数値へのキャスト時に奇妙な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のバージョンは、Windows Server 2003 32ビット上の2008 R2です。

これは既知のバグですか?SQL Server用のパッチはありますか?


コメントは詳細なディスカッション用ではありません。この会話はチャットに移動さました
ポールホワイトはGoFundMonicaを言う

回答:


20

2008 R1 SP3 10.00.5512で再現できましたが、最新のCU(14)をインストールすると修正されました。

介在するバージョンで修正されたバグを確認すると、次の修正を含むビルドにアップグレードする必要があるかのように見えます。

SQL Server 2008またはSQL Server 2012のIN句に多くの定数値を含むクエリを実行するとアクセス違反が発生する

2008 R2を使用している場合、SP1には少なくともCU 9、SP2にはCU 5が必要です。

症状の説明はやや簡潔ですが、データ型の不一致に言及しています

Microsoft SQL Server 2008、Microsoft SQL Server 2012、またはMicrosoft SQL Server 2008 R2のIN句に多くの定数値を含むクエリを実行すると、アクセス違反が発生する場合があります。

注問題が発生するために、IN句の定数は列のデータ型と完全に一致することはできません。

「多く」を定義するものではありません。私が行ったテストから、これは「20以上」を意味するのではないかと疑っています。これは、カーディナリティを推定する2つの異なる方法のカットオフポイントであるためです。

クラッシュはCScaOp_In::FCalcSelectivity()LoadHistogramFromXVariantArray()やなどの名前で呼び出されるいくつかのメソッド内で発生していましたCInMemHistogram::FJoin() -> WalkHistograms()

リスト項目の19以下の個別の場合、これらのメソッドはまったく呼び出されませんでした。同様のSQL Severを2000バグはまた、重要なポイントとしてオフこのカットに言及しています。

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はなく、推定行が生成されます)。195296

BETWEEN カーディナリティ推定値を計算するさらに別の方法を使用しているようです。

where mpnr BETWEEN 1 AND 201829.6行のみを推定します。表示されたヒストグラムからそれがどのように導出されるのかわかりません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.