2010-12-06 9 views
6

新しく作成された空のテーブルに単純な外部キー制約を追加する際に問題が発生しています。参照表は40レコード未満の小さなものですが、かなり参考になります。外部キー制約を追加するとメモリが吸い上げられ、ページングが発生する

新しいテーブルが正常に作成されますが、FK制約を追加すると、実際にはかなり時間がかかると思ってCPU負荷が増加します。メモリ使用量が増加すると、サーバーは狂気のようにページングを開始し、応答しなくなります(接続のタイムアウト)。クエリのキャンセルは役に立ちません。動作する唯一のものは、サーバーを再起動することです。非常にコストがかかります。

私が実行しようとしているスクリプトは次のとおりです。私はSQLサーバーの達人が助けることを望んでいます。どうも!

USE [my_db] 
GO 

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE TABLE [dbo].[MyNewTable](
    [Column1ID] [int] NOT NULL, 
    [Column2ID] [int] NOT NULL 
) ON [PRIMARY] 

GO 

ALTER TABLE [dbo].[MyNewTable] WITH CHECK ADD CONSTRAINT [FK_MyNewTable_Column1ID] FOREIGN KEY([Column1ID]) 
REFERENCES [dbo].[ReferenceTable] ([Column1ID]) 
ON UPDATE CASCADE 
ON DELETE CASCADE 
GO 

ALTER TABLE [dbo].[MyNewTable] CHECK CONSTRAINT [FK_MyNewTable_Column1ID] 
GO 

EDITは:Column1IDは、他のテーブルで多くのことを参照され

[Column1ID] [int] IDENTITY(1,1) NOT NULL, 
[TxtCol1] [varchar](50) NOT NULL, 
[TxtCol2] [varchar](50) NOT NULL, 
[TxtCol3] [varchar](200) NOT NULL, 
[TxtCol4] [nvarchar](2000) NOT NULL, 
[TxtCol5] [varchar](200) NOT NULL, 
[BitCol1] [bit] NOT NULL, 
[TxtCol6] [varchar](200) NOT NULL, 
[NumCol1] [smallint] NOT NULL, 
[ExternalColumnId] [int] NOT NULL, 
[NumCol2] [int] NOT NULL 

(FKさん):ReferenceTableは次のようになります小さなテーブルです。 ExternalColumnIdは別のテーブルへのFKです。この問題は、ALTER TABLE呼び出しの1つの間に発生します。残念ながら、それらの両方が一緒に実行されたので、私はそれを引き起こしたものを言うことができません。

EDIT:DBが「思考」モードになったら、シングルモードに切り替えてからマルチユーザーモードに戻って元の状態に戻すことができます。サーバをリブートするよりはるかに良いですが、依然として受け入れられません。

+0

Strange。 'ReferenceTable'の定義は何ですか?その後、すべてのステートメントは間違っていますか? '追加拘束 'は? –

+0

詳細を追加しました。元のテーブルになかったことの1つは主キーです。新しいテーブルが空であると考えると、どんなに効果があるのでしょうか? –

+0

Gbnが正しかったと私はかなりあなたがオブジェクトのロックを見ていると確信しています。再現性がありましたか?私はsqlserverについては十分に分かっていませんが、マウントされたドライブのデータファイルによって提供され、新しいテーブルスペースを作成して問題が終了するかどうかを確認できます(oracleとsql serverは並行していると仮定します)) –

答えて

4

ランダムな考え:トランザクションは開いていますか?

...(DDLほとんどの場合と同様に)ALTER TABLEは排他的アクセスが必要になりますし、それは順番に順番に他のクエリをブロックしますReferenceTableを、ブロックするスキーマロックによってブロックされていているかもしれません

+0

私の同僚それは、DBバックアップが同時に実行されているように見えます。しかし、参照テーブルがどれくらい小さいか(〜40レコード)を考えると、それはそのような問題を引き起こすでしょうか? –

+0

...ロックではCPUやメモリの使用量が有意に増加していないと思います... – pascal

+0

@pascal:それは可能です。ロックはリソースを必要とし、長いトランザクションはLDFの増加を引き起こす可能性があります。チェックポイントの処理が遅くなり、ブロックされているスレッドがブロックされていますが、独自のロックが発生します... – gbn

0

私は、各クエリバッチを単独で実行することをお勧めします。

まず、テーブルを作成し、それが成功するかどうかを確認します。

次に、WITH CHECKの代わりにWITH NOCHECKを使用して、独自の外部キー制約を追加してみてください。 WITH NOCHECKは、制約が作成されている間に、MyNewTable.Column1IDの内容の検証を、参照先テーブルの列の値と比較して抑制します。 MyNewTableが空であるか少数の行しかない場合は、これは大きな効果があるとは思わないでしょうが、あなたのような症状が発生しました。ただし、新しい制約を取得する表には何百万もの行があります。

最後に、最後のバッチを実行して、新しい制約にWITH CHECKを設定してみてください。この場合、新しいFKセットWITH NOCHECKのままにする必要がありますが、WITH NOCHECKで定義された制約は、クエリオプティマイザによって無視され、WITH CHECKに戻されるまで推奨されません。

0

この問題が再現可能であれば、Microsoftサポートのケースを開くことをお勧めします。それはバグかもしれないし、あなたはそれを打っている。既知の問題であることが判明した場合、彼らはケースを開くための料金を払い戻します。

0

解決策ではありませんが、何かにつながる可能性があります。

トリガーが定義されていますか?

新しいテーブルを作成しているとき、またはアイドル状態のときにデータベースが使用されているかアクセスされていますか?

参照テーブルの中で何か(展開時またはそれ以外の場合)UPDATE Column1IDを実行するか、そのテーブルの行を削除しますか?

参照テーブルのColumn1IDにプライマリキーまたはユニーク制約がありますか? (リストされているものはありませんが、存在しなければSQLがすぐに失敗すると思います。)

関連する問題