1

Ich entwerfe eine Multi-Modul C#/SQL Server-basierte Anwendung. Mein Entwurf ist, alle allgemeinen Nachschlagenwerte in einer Tabelle zu halten, die KeyTypeValues genannt wird. Diese Tabelle bezieht sich auf KeyTypes, die definiert, um welche Art von Daten es sich handelt.Problematische Datenbank-Design verursacht Leistungsprobleme

Zum Beispiel:

oms.KeyTypes 
------------ 
Id   INT NOT NULL IDENTITY(1,1) PRIMARY KEY 
KeyTypeName VARCHAR(40) NOT NULL 
... 

oms.KeyTypeValues 
----------------- 
Id     INT NOT NULL IDENTITY(1,1) PRIMARY KEY 
KeyTypeId   INT NOT NULL (FOREIGN KEY to oms.KeyTypes Id) 
KeyTypeValueMeaning VARCHAR(80) NOT NULL 
... 

oms.KeyTypes Beispieldaten:

Id KeyTypeName   KeyTypeDescription 
-- -----------   ------------------ 
1 RES_MFGS   Resource Manufacturers 
2 RES_OWNERSHIP_TYPES Resource Ownership Types 
... 

oms.KeyTypeValues ​​Daten Beispiel:

Id KeyTypeId KeyTypeValueMeaning 
-- --------- ------------------- 
1 1   Ford 
2 1   Chevrolet 
3 2   Owned 
4 2   Leased 
... 

So ist die Idee, dass ich nicht habe um separate Manufacturers, OwnershipType, Model usw. etc. Tabellen zu erstellen, wie wir benötigen keine weiteren Informationen über diese Werte außer ihrem Wert. Momentan habe ich etwa 88 bereits definiert und das Design hat bei mir gut funktioniert.

Ich arbeite an einer Problemabfrage, die mir Leistungsprobleme beim Beitritt aus einer Tabelle mit dem Namen res.ResourceItems. Ich muss 6 Mal für verschiedene Lookups auf die KeyTypeValues Tabelle zugreifen.

Teil ResourceItems Definition:

res.ResourceItems 
----------------- 
Id    INT NOT NULL IDENTITY(1,1) PRIMARY KEY 
OwnsershipTypeId INT NOT NULL 
ManufacturerId INT NOT NULL 
... 

Wenn ich mein Problem Schlüsselart (RES_OWNERSHIP_TYPES) zu beseitigen, kann ich es laufen weit offen, und es zieht sich zurück ~ 112.000 Zeilen mit mehr als 70 Spalten in etwa 17 Sekunden. Die Leistung ist nicht fantastisch, aber wenn man bedenkt, dass ich mich an 9 zusätzliche Tische anschließen muss, ist das akzeptabel. Wenn ich jedoch die Verknüpfung zum Abrufen von RES_OWNERSHIP_TYPES hinzufüge, springt die Ausführungszeit auf 45 Sekunden. Der Schlüsseltyp RES_OWNERSHIP_TYPES hat nur 3 mögliche Werte an diesem Punkt und oms.KeyTypeValues hat nur etwa 3.000 Datensätze insgesamt. Es wird im Laufe der Zeit weiter langsam wachsen, da wir dem System, das gebaut wird, mehr hinzufügen.

Ich weiß, dass das Ziehen von Besitztypen und das Erstellen einer enum stattdessen eine effizientere Möglichkeit wäre, dies zu handhaben, da es unwahrscheinlich ist, dass wir mehr Eigentumsarten haben werden; Ich bin jedoch besorgt über das Gesamtdesign, wo solch ein dramatischer Leistungseinbruch stattfindet.

Ich habe Fremdschlüsselbeziehungen von res.ResourceItems bis oms.KeyTypeValues für alle Id-Werte. Ich habe auch Non-Unique, Non-Clustered-Index-Setup auf oms.KeyTypeValues.Id Spalte. Ich habe sie neu aufgebaut, um die Fragmentierung zu beseitigen.

Als Test, habe ich getrennte KeyTypes und KeyTypeValues Tabellen in meinem res Schema und geladen nur mit RES_OWNERSHIP_TYPES Werten und trat zu ihm, und der Ausführungszeit auf etwa 17 Sekunden ging zurück. Ich würde das lieber nicht ausführen, da es meine Absicht besiegt und ein großes Problem zu lösen scheint.

Ich kann nicht feststellen, warum es so einen großen Hit nur mit diesem Join gibt und hoffte, dass jemand Einblick in das haben könnte, was ich übersehen könnte. Ich werde gerne mehr von der Datenbank-Design teilen, wenn nötig.

+0

Verwenden Sie [Indizes abdecken] (http://www.dbadiaries.com/sql-server-covering-index-and-key-lookup/). Beachten Sie, dass SQL Server 2005 und höhere Versionen [enthaltene Spalten] (http://msdn.microsoft.com/en-us/library/ms190806.aspx) sowie zusammengesetzte Indizes unterstützen. – HABO

Antwort

0

Wenn das Hinzufügen einer Verknüpfung zu einer Tabelle mit 3 Datensätzen die Leistung erheblich beeinträchtigt, bedeutet dies, dass sich der Abfrageplan mit dem Hinzufügen dieser Verknüpfung dramatisch ändert.

Die schnelle und schmutzige Sache zu versuchen ist, sp_updatestats einmal laufen zu lassen, um zu sehen, ob das dein Problem löst (und ich denke, dass es wahrscheinlich wird). Dadurch wird SQL Server angewiesen, die Statistiken für alle Tabellen und Indizes zu aktualisieren und die Auswahl von Abfrageplänen zu erleichtern.

Die gründlichere Lösung ist es, die Ausführungspläne der beiden Varianten der Abfrage zu vergleichen, um zu verstehen, warum Leistung leidet. Dies sollte Aufschluss darüber geben, wie die Leistung verbessert werden kann. Ich rate nicht, die Tabelle zu entfernen und eine Nur-Code-Enum zu nehmen. Wenn die Dinge richtig funktionieren, sollte es keinen erkennbaren Leistungsunterschied beim Beitritt in diese zusätzliche Tabelle geben.

+0

Ich habe sowohl Ihre und @FLICKER Vorschlag und beide geholfen. Einfaches Ausführen von 'sp_updatestats' hat den größten Einfluss, wenn man unter 20 Sekunden zurückkommt. Das Hinzufügen zusätzlicher Indizes und die Verwendung von Unterabfragen wurden um weitere Sekunden verkürzt, sodass beide Abfragen jetzt gleich wirksam sind. – bassrek

1

Ich schlage vor, Sie verwenden sub-query statt JOIN

Manchmal, wenn Lookup-Tabelle klein ist (als Lookup-Tabelle ist), sub-query arbeitet schneller als JOIN

wir nicht haben, aber die tatsächlichen Daten und don Habe keinen Ausführungsplan, also solltest du verschiedene Antworten als Vorschlag ausprobieren und sehen, welcher für dich funktioniert.

Falls dies nicht funktionierte, versuchen Sie, zusätzlich zu den referenzierten Feldern einen Index für referenzierende Felder hinzuzufügen.

BTW, ich glaube nicht, dass Ihr Design schlecht ist. Ich habe solche Nachschlagetabellen in vielen verschiedenen Systemen gesehen.

+0

Danke - Ich wünschte ich könnte sowohl deine als auch @Tim als Antworten markieren; Die Aktualisierung der Statistiken schien jedoch der größte Schuldige zu sein. Ich experimentierte mit Unterabfragen und zusätzlichen Indizes und konnte einige zusätzliche Sekunden abschneiden. Danke für den Kommentar zum Design - ja, ich habe diese Art von Design in verschiedenen Systemen verwendet und es ist ziemlich gut, denke ich. – bassrek

+0

Statistiken auf dem neuesten Stand zu halten ist immer eine gute Sache. Danke für die Abstimmung :) – FLICKER