Ich habe eine Competitions
Ergebnistabelle, die einerseits die Namen der Teammitglieder und deren Rangliste enthält.
Auf der anderen Seite muss ich eine Tabelle mit eindeutigen Namen von Wettbewerbern führen :
CREATE TABLE Competitors (cName nvarchar(64) primary key)
Jetzt habe ich ungefähr 200.000 Ergebnisse in der 1. Tabelle und wenn die Wettbewerbstabelle leer ist, kann ich Folgendes ausführen:
INSERT INTO Competitors SELECT DISTINCT Name FROM CompResults
Die Abfrage dauert nur etwa 5 Sekunden, um etwa 11.000 Namen einzufügen.
Bisher ist dies keine kritische Anwendung, daher kann ich in Betracht ziehen, die Wettbewerbstabelle einmal im Monat abzuschneiden, wenn ich die neuen Wettbewerbsergebnisse mit etwa 10.000 Zeilen erhalte.
Aber was ist die beste Vorgehensweise, wenn neue Ergebnisse mit neuen UND bestehenden Wettbewerbern hinzugefügt werden? Ich möchte die vorhandene Wettbewerbstabelle nicht abschneiden
Ich muss die INSERT-Anweisung nur für neue Wettbewerber ausführen und nichts tun, wenn sie vorhanden sind.
quelle
NVARCHAR(64)
Spalte Ihre primäre (und damit: Clustering) Schlüssel !! Zuallererst - es ist ein sehr breiter Schlüssel - bis zu 128 Bytes; und zweitens ist es eine variable Größe - wieder: nicht optimal ... Dies ist die schlechteste Wahl, die Sie treffen können - Ihre Leistung wird die Hölle sein und die Fragmentierung von Tabellen und Indizes wird die ganze Zeit bei 99,9% liegen .....cName
Fehler in drei von vier Kategorien ... (es ist nicht eng, es ist wahrscheinlich nicht statisch und es wird definitiv nicht immer größer)Antworten:
Semantisch fragen Sie "Konkurrenten einfügen, wo es noch keine gibt":
quelle
Eine andere Möglichkeit besteht darin, Ihre Ergebnistabelle mit der Tabelle Ihrer vorhandenen Konkurrenten zu verknüpfen und die neuen Konkurrenten zu finden, indem Sie die unterschiedlichen Datensätze filtern, die nicht mit dem Join übereinstimmen:
Die neue Syntax MERGE bietet auch eine kompakte, elegante und effiziente Möglichkeit, dies zu tun:
quelle
Ich weiß nicht, warum das noch niemand gesagt hat.
NORMALISIEREN.
Sie haben einen Tisch, an dem Wettbewerbe modelliert werden? Wettbewerbe bestehen aus Wettbewerbern? Sie benötigen eine eindeutige Liste der Wettbewerber in einem oder mehreren Wettbewerben ......
Sie sollten die folgenden Tabellen haben .....
Mit Einschränkungen für CompetitionCompetitors.CompetitionID und CompetitorID, die auf die anderen Tabellen zeigen.
Mit dieser Art von Tabellenstruktur - Ihre Schlüssel sind alle einfache INTS - scheint es keinen guten NATÜRLICHEN SCHLÜSSEL zu geben, der zum Modell passt, daher denke ich, dass ein SURROGATE-SCHLÜSSEL hier gut passt.
Wenn Sie dies also hatten, um die eindeutige Liste der Wettbewerber in einem bestimmten Wettbewerb zu erhalten, können Sie eine Abfrage wie die folgende ausstellen:
Und wenn Sie die Punktzahl für jeden Wettbewerb haben möchten, an dem ein Teilnehmer teilnimmt:
Und wenn Sie einen neuen Wettbewerb mit neuen Wettbewerbern haben, überprüfen Sie einfach, welche bereits in der Wettbewerbstabelle vorhanden sind. Wenn sie bereits vorhanden sind, fügen Sie sie nicht in den Wettbewerber für diese Wettbewerber ein und fügen sie für die neuen ein.
Dann fügen Sie den neuen Wettbewerb in Wettbewerb ein und schließlich stellen Sie einfach alle Links in CompetitionCompetitors her.
quelle
Sie müssen die Tabellen zusammenfügen und eine Liste der eindeutigen Konkurrenten erhalten, die noch nicht vorhanden sind
Competitors
.Dadurch werden eindeutige Datensätze eingefügt.
Es kann vorkommen, dass diese Einfügung schnell erfolgen muss, ohne auf die Auswahl eindeutiger Namen warten zu müssen. In diesem Fall können Sie die eindeutigen Namen in eine temporäre Tabelle einfügen und diese temporäre Tabelle dann zum Einfügen in Ihre reale Tabelle verwenden. Dies funktioniert gut, da die gesamte Verarbeitung zum Zeitpunkt des Einfügens in eine temporäre Tabelle erfolgt, sodass Ihre reale Tabelle nicht beeinträchtigt wird. Wenn Sie die gesamte Verarbeitung abgeschlossen haben, fügen Sie sie schnell in die reale Tabelle ein. Ich könnte sogar den letzten Teil, den Sie in die reale Tabelle einfügen, in eine Transaktion einbinden.
quelle
Die Antworten, die über Normalisierung sprechen, sind großartig! Aber was ist, wenn Sie sich in einer Position wie mir befinden, in der Sie das Datenbankschema oder die Datenbankstruktur in ihrer jetzigen Form nicht berühren dürfen? ZB sind die DBAs 'Götter' und alle vorgeschlagenen Revisionen gehen zu / dev / null?
In dieser Hinsicht habe ich das Gefühl, dass dies auch mit diesem Stack Overflow-Posting in Bezug auf alle oben genannten Benutzer beantwortet wurde , die Codebeispiele geben.
Ich reposte den Code von INSERT VALUES WHERE NOT EXISTS, was mir am meisten geholfen hat, da ich keine zugrunde liegenden Datenbanktabellen ändern kann:
Der obige Code verwendet andere Felder als das, was Sie haben, aber Sie erhalten den allgemeinen Überblick über die verschiedenen Techniken.
Beachten Sie, dass dieser Code gemäß der ursprünglichen Antwort auf Stack Overflow von hier kopiert wurde .
Mein Punkt ist jedenfalls, dass "Best Practice" oft darauf ankommt, was man kann und was nicht, genauso gut wie auf Theorie.
Viel Glück!
quelle
Das Normalisieren Ihrer Betriebstabellen, wie von Transact Charlie vorgeschlagen, ist eine gute Idee und erspart im Laufe der Zeit viele Kopfschmerzen und Probleme. Es gibt jedoch Schnittstellentabellen , die die Integration in externe Systeme unterstützen, und Berichtstabellen , die beispielsweise analytische Funktionen unterstützen wird bearbeitet; und diese Arten von Tabellen sollten nicht unbedingt normalisiert werden - tatsächlich ist es sehr oft viel, viel bequemer und performanter, wenn sie es nicht sind .
In diesem Fall halte ich den Vorschlag von Transact Charlie für Ihre Operationstische für gut.
Ich würde jedoch einen Index (nicht unbedingt eindeutig) zu CompetitorName in der Competitors-Tabelle hinzufügen, um effiziente Verknüpfungen zu CompetitorName zum Zwecke der Integration (Laden von Daten aus externen Quellen) zu unterstützen, und ich würde eine Schnittstellentabelle in den Mix einfügen: CompetitionResults.
Wettbewerbsergebnisse sollten alle Daten enthalten, die Ihre Wettbewerbsergebnisse enthalten. Der Zweck einer solchen Schnittstellentabelle besteht darin, das Abschneiden und erneute Laden aus einer Excel-Tabelle, einer CSV-Datei oder einer beliebigen Form, in der Sie diese Daten haben, so schnell und einfach wie möglich zu gestalten.
Diese Schnittstellentabelle sollte nicht als Teil des normalisierten Satzes von Betriebstabellen betrachtet werden. Anschließend können Sie sich mit CompetitionResults verbinden, wie von Richard vorgeschlagen, um Datensätze in Wettbewerber einzufügen, die noch nicht vorhanden sind, und diejenigen zu aktualisieren, die dies tun (z. B. wenn Sie tatsächlich mehr Informationen über Wettbewerber haben, wie z. B. deren Telefonnummer oder E-Mail-Adresse).
Eine Sache, die ich beachten möchte - in Wirklichkeit ist es sehr unwahrscheinlich, dass der Name des Mitbewerbers in Ihren Daten eindeutig ist . Bei 200.000 Wettbewerbern können Sie beispielsweise zwei oder mehr David Smiths haben. Daher würde ich empfehlen, dass Sie mehr Informationen von Wettbewerbern sammeln, z. B. deren Telefonnummer oder E-Mail-Adresse oder etwas, das mit größerer Wahrscheinlichkeit eindeutig ist.
Ihre Betriebstabelle "Wettbewerber" sollte nur eine Spalte für jedes Datenelement enthalten, das zu einem zusammengesetzten natürlichen Schlüssel beiträgt. Beispielsweise sollte es eine Spalte für eine primäre E-Mail-Adresse geben. Die Schnittstellentabelle sollte jedoch einen Steckplatz für alte und neue Werte für eine primäre E-Mail-Adresse enthalten, damit der alte Wert verwendet werden kann, um den Datensatz in Mitbewerbern nachzuschlagen und diesen Teil auf den neuen Wert zu aktualisieren.
Daher sollten CompetitionResults einige "alte" und "neue" Felder enthalten - oldEmail, newEmail, oldPhone, newPhone usw. Auf diese Weise können Sie in Competitors einen zusammengesetzten Schlüssel aus CompetitorName, Email und Phone bilden.
Wenn Sie dann einige Wettbewerbsergebnisse haben, können Sie Ihre CompetitionResults-Tabelle von Ihrer Excel-Tabelle oder von allem, was Sie haben, abschneiden und neu laden und eine einzelne, effiziente Einfügung ausführen, um alle neuen Wettbewerber in die Competitors-Tabelle einzufügen, sowie eine einzelne, effiziente Aktualisierung, um sie zu aktualisieren Alle Informationen zu den bestehenden Wettbewerbern aus den Wettbewerbsergebnissen. Sie können eine einzelne Einfügung vornehmen, um neue Zeilen in die CompetitionCompetitors-Tabelle einzufügen. Diese Dinge können in einer gespeicherten Prozedur von ProcessCompetitionResults ausgeführt werden, die nach dem Laden der CompetitionResults-Tabelle ausgeführt werden kann.
Dies ist eine Art rudimentäre Beschreibung dessen, was ich in der realen Welt mit Oracle Applications, SAP, PeopleSoft und einer Wäscheliste anderer Unternehmenssoftware-Suiten immer wieder gesehen habe.
Ein letzter Kommentar, den ich machen möchte, ist einer, den ich zuvor zu SO gemacht habe: Wenn Sie einen Fremdschlüssel erstellen, der sicherstellt, dass ein Konkurrent in der Konkurrententabelle vorhanden ist, bevor Sie CompetitionCompetitors eine Zeile mit diesem Konkurrenten hinzufügen können, stellen Sie dies sicher Der Fremdschlüssel ist so eingestellt, dass Aktualisierungen und Löschungen kaskadiert werden . Auf diese Weise können Sie einen Konkurrenten löschen, und alle mit diesem Konkurrenten verknüpften Zeilen werden automatisch gelöscht. Andernfalls müssen Sie für den Fremdschlüssel standardmäßig alle zugehörigen Zeilen aus CompetitionCompetitors löschen, bevor Sie einen Mitbewerber löschen können.
(Einige Leute denken, dass nicht kaskadierende Fremdschlüssel eine gute Sicherheitsmaßnahme sind, aber meine Erfahrung ist, dass sie nur ein verdammter Schmerz im Hintern sind, der meistens nur das Ergebnis eines Versehens ist und eine Menge Arbeit schafft Für DBAs. Der Umgang mit Personen, die versehentlich Inhalte löschen, ist der Grund, warum Sie Dinge wie "Sind Sie sicher" -Dialoge und verschiedene Arten von regelmäßigen Sicherungen und redundanten Datenquellen haben. Es ist weitaus üblicher, einen Konkurrenten tatsächlich löschen zu wollen, dessen Daten alle sind vermasselt zum Beispiel, als es ist, versehentlich einen zu löschen und dann zu sagen: "Oh nein! Ich wollte das nicht tun! Und jetzt habe ich nicht ihre Wettbewerbsergebnisse! Aaaahh!" Letzteres ist sicherlich häufig genug, also Sie müssen darauf vorbereitet sein, aber ersteres ist weitaus häufiger.Der einfachste und beste Weg, sich auf das erstere vorzubereiten, besteht darin, nur Aktualisierungen und Löschungen für Fremdschlüsselkaskaden vorzunehmen.)
quelle
Ok, dies wurde vor 7 Jahren gefragt, aber ich denke, die beste Lösung besteht darin, auf die neue Tabelle vollständig zu verzichten und dies einfach als benutzerdefinierte Ansicht zu tun. Auf diese Weise duplizieren Sie keine Daten, machen sich keine Sorgen um eindeutige Daten und berühren nicht die tatsächliche Datenbankstruktur. Etwas wie das:
Hier können andere Elemente hinzugefügt werden, z. B. Verknüpfungen in anderen Tabellen, WHERE-Klauseln usw. Dies ist höchstwahrscheinlich die eleganteste Lösung für dieses Problem, da Sie jetzt nur die Ansicht abfragen können:
... und fügen Sie der Ansichtsabfrage alle WHERE-, IN- oder EXISTS-Klauseln hinzu.
quelle