2010-12-06 13 views
6

Ich habe viele Probleme beim Hinzufügen einer einfachen Fremdschlüsseleinschränkung zu einer neu erstellten leeren Tabelle. Die Referenztabelle ist winzig mit weniger als 40 Datensätzen, aber sie wird ziemlich referenziert.Hinzufügen von Foreign Key Constraint saugt Speicher auf und verursacht Paging

Folgendes passiert: Neue Tabelle wird erfolgreich erstellt, aber wenn eine FK-Einschränkung hinzugefügt wird, "denkt" sie sehr lange und erhöht die CPU-Last. Die Speicherauslastung steigt, der Server beginnt wie verrückt zu paging und reagiert nicht mehr (Verbindungstimeout). Das Abbrechen der Abfrage hilft nicht. Das einzige, was funktioniert, ist ein Neustart des Servers, was sehr kostspielig ist.

Hier ist das Skript, das ich ausführen möchte. Ich hoffe, SQL-Server-Gurus können helfen. Danke!

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: ReferenceTable ist eine kleine Tabelle, die etwa wie folgt aussieht:

[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 

Column1ID eine Menge von anderen Tabellen (FK ist) verwiesen wird. ExternalColumnId ist ein FK zu einer anderen Tabelle. Das Problem tritt während eines der ALTER TABLE-Aufrufe auf. Leider wurden beide zusammen geführt, so dass ich nicht sagen kann, welches das verursacht hat.

BEARBEITEN: Sobald der DB in den "Denkmodus" wechselt, ist es möglich, ihn wieder in den Einzelmodus und dann zurück in den Mehrbenutzermodus zu versetzen. Es ist viel besser als einen Neustart des Servers, aber immer noch inakzeptabel.

+0

Seltsam. Was ist die Definition von 'ReferenzTabelle'? Nach welcher Aussage geht alles schief? Der 'ADD CONSTRAINT'? –

+0

Gerade hinzugefügt mehr Info. Eine Sache, die ich in der ursprünglichen Tabelle nicht hatte, ist ein Primärschlüssel. Irgendeine Idee, wie viel Wirkung das haben würde, wenn man bedenkt, dass die neue Tabelle leer ist? –

+0

Gbn ist richtig, und ich bin mir ziemlich sicher, dass Sie Objektverriegelung betrachten. War es reproduzierbar? Ich kenne sqlserver nicht genug, aber Sie könnten versuchen, einen neuen Tablespace zu erstellen, der von einer Datendatei in einem gemounteten Laufwerk bedient wird und prüft, ob das Problem existiert. (Ich nehme an, Oracle und SQL Server haben Parallelen;)) –

Antwort

4

Zufälliger Gedanke: Haben Sie eine Transaktion offen?

Das wird ALTER TABLE exklusiven Zugriff erfordern (wie DDL hat die meisten), und es könnte sein, dass es durch eine Schemasperre blockiert ist, was wiederum ReferenceTable blockiert, was wiederum andere Abfragen blockieren ...

+0

Nach Rücksprache mit meinem Kollegen sieht es so aus, als ob ein DB-Backup zur selben Zeit läuft. Aber wenn man bedenkt, wie klein die Referenztabelle ist (~ 40 Datensätze), würde dies ein solches Problem verursachen? –

+0

... Ich glaube, eine Sperre hätte nicht dazu geführt, dass die CPU oder die Speichernutzung signifikant ansteigt ... – pascal

+0

@pascal: es könnte; Sperren erfordern Ressourcen, eine lange Transaktion kann LDF Wachstum verursachen, möglicherweise mehr Checkpoint-Verarbeitung, blockierte Threads blockiert werden, aber ihre eigenen Sperren haben ... – gbn

0

Ich würde vorschlagen, jeden Abfrage-Batch isoliert auszuführen.

Zuerst erstellen Sie die Tabelle und sehen, ob das gelingt.

Versuchen Sie als Nächstes, die Fremdschlüsseleinschränkung unter Verwendung von WITH NOCHECK anstelle von WITH CHECK hinzuzufügen. WITH NOCHECK unterdrückt jede Überprüfung des Inhalts in MyNewTable.Column1ID gegen die Werte in der Spalte der referenzierten Tabelle, während die Einschränkung erstellt wird. Wenn MyNewTable leer ist oder wenige Zeilen hat, würde ich nicht denken, dass dies viel bewirken würde, aber ich habe Symptome wie beschrieben gefunden - außer dass die Tabelle, die die neue Einschränkung erhält, Millionen von Zeilen enthält.

Schließlich führen Sie Ihren letzten Stapel, um zu versuchen, WITH CHECK auf Ihre neue Einschränkung einzustellen. Wenn dies nicht möglich ist, müssen Sie nur den neuen FK-Satz WITH NOCHECK belassen. Dies wird jedoch nicht empfohlen, da die Einschränkungen WITH NOCHECK vom Abfrageoptimierer ignoriert werden, bis sie auf WITH CHECK zurückgesetzt werden.

0

Wenn dieses Problem reproduzierbar ist, empfehle ich Ihnen, einen Microsoft Support-Fall zu öffnen. Vielleicht ist es ein Fehler und Sie treffen es. Wenn festgestellt wird, dass es sich um ein bekanntes Problem handelt, werden Ihnen die Kosten für die Öffnung des Falles erstattet.

0

Eine Handvoll Dinge zu prüfen - keine Lösungen, aber sie könnten zu etwas führen.

Sind Trigger definiert?

Wird die Datenbank zum Zeitpunkt der Erstellung der neuen Tabelle verwendet oder aufgerufen, oder ist sie inaktiv?

Trifft (zum Zeitpunkt der Bereitstellung oder anderweitig) UPDATE Column1ID in der Referenztabelle oder Zeilen in dieser Tabelle löschen?

Gibt es einen Primärschlüssel oder eine eindeutige Einschränkung für Column1ID in der Referenztabelle? (Sie haben keine aufgelistet, aber ich würde denken, SQL würde fehlschlagen, wenn einer nicht vorhanden wäre.)

Verwandte Themen