Ist es eine schlechte Praxis, Daten aus verschiedenen Tabellen in einer zusammenzufassen?

12

Hintergrund

Ich schreibe viele große Berichte für eine große Datenbank mit Gesundheitsdaten (SPs, Funktionen, Jobs usw. schreiben) und verwalte diese im Allgemeinen. Das ursprüngliche Schema und die Software, die es verwendet, stammen von einem anderen Anbieter, sodass ich strukturell nicht viel daran ändern kann. Es gibt viele Aufzeichnungen, die nachverfolgt werden müssen, z. B. Labors, Verfahren, Impfstoffe usw., und sie sind über Dutzende von Tabellen verteilt, von denen viele aufgebläht und schlecht indiziert sind (ich konnte dies etwas korrigieren).

Das Problem

Das Problem ist, dass wir nur wenig Kontrolle über die Datenbank haben und dass es schwierig und langwierig ist, diese Berichte zu schreiben und zu pflegen, da sie von einem bestimmten Update oder Patch geändert werden können - insbesondere, wenn große Überschneidungen auftreten. Alles was es braucht ist ein Patch und ich stecke fest, große Teile eines Dutzends von Berichten neu zu schreiben. Darüber hinaus werden Abfragen schnell und langsam verschleiert, wenn Verknüpfungen, verschachtelte Auswahlen und das Anwenden von Stapeln ausgeführt werden.

Meine Lösung"

Mein Plan war es, alle diese Datensätze in eine "Catch-All" -Tabelle zu schreiben und Trigger auf die Originaltabellen zu schreiben, um die Datensätze in dieser Aggregattabelle zu verwalten. Natürlich müsste ich sicherstellen, dass meine Auslöser nach den Aktualisierungen intakt sind, aber dies wäre vom Standpunkt der Wartbarkeit viel einfacher und würde nur auf die Daten verweisen.

Die Tabelle wäre dünn und lang und würde nur die erforderlichen Daten speichern.

CREATE TABLE dbo.HCM_Event_Log (
    id INT IDENTITY,
    type_id INT NULL,
    orig_id VARCHAR(36) NULL,
    patient_id UNIQUEIDENTIFIER NOT NULL,
    visit_id UNIQUEIDENTIFIER NULL,
    lookup_id VARCHAR(50) NULL,
    status VARCHAR(15) NULL,
    ordered_datetime DATETIME NULL,
    completed_datetime DATETIME NULL,
    CONSTRAINT PK_HCM_Event_Log PRIMARY KEY CLUSTERED (id)
)

Dann hätte ich verschiedene relationale Tabellen für Dinge wie type_id und item groupings.

Ich fange an, diese Idee zu überdenken, da einige dieser Tabellen zu einem großen Teil geschrieben sind. Die SPs und Berichte, die ich schreiben würde, würden auch auf die Daten verweisen. Ich befürchte, dass diese Tabelle mit so viel E / A zu einem Albtraum für das Sperren und Ausführen von Datensätzen wird.

Meine Frage

Ist eine schlechte oder eine gute Idee? Ich stelle fest, dass jede Situation in SQL Server (2008 r2 Standard Edition BTW) und der "manchmal" -Regel anders ist, aber ich suche wirklich nur nach allgemeinen Ratschlägen.

Ich habe angefangen, einen Service Broker in Betracht zu ziehen, aber ich führe nur einfache Aktualisierungen / Einfügungen durch ( siehe Alternative zur akzeptierten Antwort ). In vielen Fällen müssen die Daten in Echtzeit vorliegen, sodass die Verwendung einer Sicherungsdatenbank nicht wirklich funktioniert. Die Leistung ist für uns bereits ein Problem, aber das meiste davon hängt mit der Hardware zusammen, die in Kürze behoben wird.

jreed121
quelle
1
Können Sie geplante Ausfälle durchsetzen? Wenn eines dieser Updates keinen Trigger auslöscht und Sie Ihre Aggregate nicht aktualisieren, führt dies möglicherweise zu fehlerhaften Daten.
Erik
Sie überlegen, alle Informationen zu Labors, Verfahren, Impfstoffen und Patienten in einer Tabelle zusammenzufassen? Schlechte Idee. Möglicherweise können Sie ein Sternschema verwenden, wenn dies für die Art der von Ihnen ausgeführten Abfragen geeignet ist.
Michael Green
1
Haben Sie versucht, indizierte Ansichten zu erstellen? Dadurch würde eine logische Ebene zwischen Ihrem Code und dem des Anbieters erstellt, sodass Sie die Ansicht einfach aktualisieren können, wenn der Anbieter Änderungen daran vornimmt. Außerdem werden die indizierten Ansichten für Sie vorab ausgefüllt und bieten eine gute Leseleistung. Eine der wichtigsten Überlegungen dabei ist, wie stark die Schreibvorgänge in den Datenbanktabellen des Herstellers ausgelastet sind. Dies wäre jedoch wahrscheinlich eine sauberere und leichter zu wartende Lösung als die Verwendung von Triggern usw.
Micah Nikkel
Sorry für die verspätete Antwort Jungs, danke für das Feedback. @Erik - Ja, wir haben Updates geplant und ich überprüfe anhand einer Reihe von Checklisten-Skripten, ob alle meine vorherigen Änderungen noch vorhanden sind. Es gibt also keine Überraschungen und ich behalte CREATE-Skripten für Alle Auslöser.
jreed121
@MichaelGreen - Ich werde ein Sternschema untersuchen, aber ich bin neugierig, warum es eine schlechte Idee ist, all diese Daten in einer Tabelle zu haben. Die Anwendungsumgebung ist in einem VPN vollständig isoliert und kann in keinem Fall außerhalb des Netzwerks aufgerufen werden. Wenn etwas mit dem Tisch schief geht, ist es nicht das Ende der Welt, weil ich einfach alles zurückschreiben könnte. Die Tabelle wird nicht für unternehmenskritische Daten verwendet, oder zumindest ist sie nicht der einzige oder primäre Ort, an dem Daten gespeichert werden.
jreed121

Antworten:

8

Wenn ich dich richtig verstanden habe,

  • Sie haben ein großes Drittsystem,
  • Sie haben nicht viel Kontrolle darüber,
  • Sie erstellen komplexe Berichte, in denen Daten direkt aus der Datenbank eines Drittanbieters gelesen werden.
  • Ihre Abfragen hängen von der internen Struktur der Datenbank des Drittanbieters ab.

Ich würde es so angehen:

  • Richten Sie eine eigene Datenbank ein, über die ich die volle Kontrolle habe.
  • Richten Sie einen Synchronisierungsprozess ein, der Daten aus relevanten Tabellen und Spalten aus der Datenbank eines Drittanbieters liest und in Mine einfügt / aktualisiert.
  • Entwickle meine komplexen Berichte basierend auf der stabilen Struktur meiner Datenbank.

In diesem Fall können Sie die Struktur und die Indizes Ihrer Datenbank optimieren, um die Leistung Ihrer Berichte zu verbessern, ohne das System von Drittanbietern zu beeinträchtigen. Wenn sich die ursprüngliche Datenstruktur nicht dramatisch ändert, ändert sich die Logik Ihrer Abfragen für Ihre Berichte nicht, wenn sich die Datenbank von Drittanbietern ändert. Sie müssten nur den Synchronisierungsprozess anpassen.

Der Synchronisierungsprozess ist praktisch der Konvertierungsprozess - Sie konvertieren Daten aus der Datenbank eines Drittanbieters in die von Ihnen benötigte Struktur. Ein Teil dieses Konvertierungsprozesses könnte darin bestehen, etwaige Normalisierungsprobleme der ursprünglichen Datenbank eines Drittanbieters zu beheben. Nur dieser Teil des Systems muss die interne Struktur des Drittsystems kennen und von ihr abhängig sein. Ihre Hauptberichte und Hauptabfragen hängen nur von Ihrer Datenbank ab.

Der wichtigste Punkt ist also: Trennen und begrenzen Sie den Teil Ihres Systems, der von den Interna des Drittsystems abhängt.

aktualisieren

In Bezug auf Echtzeitanforderung. Übrigens dachte ich immer, dass die Definition von "Echtzeit" "garantierte Antwortzeit" ist, nicht "eine kleine Antwortzeit". Das hängt natürlich von Ihrer Anwendung ab. In meiner Praxis reicht es aus, wenn ich zwei Datenbanken innerhalb einer Minute nach der erkannten Änderung synchronisiere. Wenn ein Benutzer einen Bericht auf dem Bildschirm sieht und einige zugrunde liegende Daten geändert werden, muss der Bericht auf irgendeine Weise erneut ausgeführt werden, um diese Änderung widerzuspiegeln. Sie können nach Änderungen suchen oder ein Ereignis / eine Nachricht abhören. Die Berichtsabfrage muss jedoch erneut ausgeführt werden, um die neuesten Änderungen anzuzeigen.

Sie möchten bereits Trigger schreiben, um Änderungen in den Originaltabellen zu erfassen und diese Änderungen in eine generische Tabelle zu schreiben. Erfassen Sie Änderungen also wie beabsichtigt, aber schreiben Sie sie in ordnungsgemäß normalisierte Tabellen, nicht in eine einzelne.

Dies ist also ein Extremfall. Die Konvertierung der Datenstruktur von Drittanbietern in Ihre interne Datenstruktur erfolgt in den Triggern, die INSERT/UPDATE/DELETEfür Tabellen von Drittanbietern ausgelöst werden. Es kann schwierig sein. Der Code der Auslöser hängt von der internen Struktur beider Systeme ab. Wenn die Konvertierung nicht trivial ist, kann sie das Original INSERT/UPDATE/DELETEbis zu ihrem Fehlschlagen verzögern . Wenn Ihr Trigger einen Fehler enthält, kann dies die ursprüngliche Transaktion bis zu ihrem Fehlschlagen beeinträchtigen. Wenn sich das System eines Drittanbieters ändert, kann dies Ihren Auslöser beschädigen, was dazu führen würde, dass Transaktionen des Drittanbieters fehlschlagen.

Weniger extremer Fall. Um den Code Ihrer Trigger einfacher und weniger fehleranfällig zu machen, schreiben Sie alle erfassten Änderungen in eine Staging- / Audit- / Diff-Tabelle, setzen Sie ein Flag und senden Sie eine Nachricht, dass Änderungen ausstehen, und starten Sie den Hauptkonvertierungsprozess durch diese Zwischentabellen und führen Sie die Konvertierung durch. Die Hauptsache hierbei ist, dass ein potenziell schwerer Konvertierungsprozess außerhalb des Umfangs der ursprünglichen Transaktion stattfinden sollte.

Auf den zweiten Blick ähnelt es Ihrem ursprünglichen Vorschlag in der Frage. Der Unterschied besteht jedoch darin, dass die Capture-All-Tabellen nur vorübergehend Daten enthalten. Die Datenmenge ist gering - genau das, was sich geändert hat. es muss kein einziger Tisch sein; Schließlich werden die Daten in separaten, ordnungsgemäß normalisierten, permanenten Tabellen gespeichert, über die Sie die volle Kontrolle haben, die unabhängig vom System eines Drittanbieters sind und die Sie für Ihre Abfragen optimieren können.

Vladimir Baranov
quelle
Wenn Sie den Batch-Transfer-Weg gehen, haben wir mit Change Tracking (und Change Data Capture, je nach Ihren Anforderungen) bei ziemlich hohen Transaktionszahlen (100.000 pro Tag) Erfolg gehabt. Es ist einfacher als die Implementierung eigener Staging- / Audit- / Diff-Tabellen und kann ohne Änderung des Anwendungscodes oder Auslöser bereitgestellt werden.
Michael Green
Sei es Trigger oder CDC, der einzige Weg, wie Sie wirklich an Echtzeit herankommen, ist Streaming oder Queuing. Warteschlangenbasiert ist ein guter Kompromiss für Latenz und Kosteneffizienz. Ihre Zeit wird für Methoden aufgewendet, um die Warteschlange schneller zu verarbeiten. Lassen Sie den Großteil der Arbeit asynchron von der Anwendung und entlasten Sie die Benutzertransaktionen weniger. In der Vergangenheit habe ich genau das gegen Allscripts Sunrise EMR mit einem Dienst getan, der die Warteschlange mit einigen parallelen foreach C # -Aufrufen verarbeitete. Die typische Latenzzeit für die Verarbeitung und Verfügbarkeit neuer Daten im Warehouse betrug unter 30 Sekunden
Brad D,
Ich habe vielleicht zu viel von "Echtzeit" gesagt, ich bin nicht zu sehr mit Millisekunden oder sogar 5 Sekunden beschäftigt, aber ich habe viele Fragen, auf die sich unsere Mitarbeiter verlassen, um den Workflow zu beschleunigen. Wenn einem Kunden etwas angetan wurde (Verfahren, Impfung usw.), müssen wir dies in kurzer Zeit nachweisen. Die Konvertierungen sind trivial und / oder nicht einmal Konvertierungen. Ich mache mir keine allzu großen Sorgen um Änderungen an den Herstellertabellen, da diese sich nicht so oft ändern, und ich muss es jetzt sowieso tun, aber ich dachte, dass es einfacher ist, einen Auslöser zu aktualisieren / neu zu erstellen, als ein Dutzend Berichte / Abfragen / SPs. Ich überprüfe nach jedem Update.
jreed121
@ jreed121, ich denke auch , dass es ist einfacher zu Update - Trigger (s) als Berichte. Sie haben wahrscheinlich einen Auslöser für jede Quelltabelle, um die Änderungen zu erfassen, sodass es wahrscheinlich mehr als einen Auslöser gibt. Versuchen Sie dennoch nicht, alle diese erfassten Änderungen in eine große denormalisierte Tabelle zu schreiben. Schreiben Sie sie in eine ordnungsgemäß normalisierte Gruppe von Tabellen. Ihre Berichte sollten auf diesen normalisierten Tabellen basieren, die Sie steuern, und nicht von möglicherweise geänderten Originaltabellen abhängen.
Vladimir Baranov
3

Stellen Sie es auf jeden Fall in einen standardisierten Satz von Tabellen, damit Sie die Importphase optimieren können, anstatt komplexe Berichte und Abfragen ändern zu müssen. Die Daten sollten dennoch normalisiert sein, was Mehrfachtabellen erfordert (aber mit guten Indizes).

Verwenden Sie, wie bereits erwähnt, keine Trigger, sondern synchronisieren Sie sie stapelweise.

Machen Sie sich keine Sorgen über viele Verknüpfungen. Wenn die Daten ordnungsgemäß normalisiert und indiziert werden, verursachen diese keine signifikanten Kosten oder Verwaltungslasten.

Die Zeit zum Denormalisieren in so etwas wie ein Data Warehouse ist, wenn Sie in der Lage sein müssen, viele verschiedene Arten von Abfragen für die Daten durchzuführen, die Sie nicht vorhersagen können. Es hat seine eigenen Nachteile und Gemeinkosten und sollte gegebenenfalls verwendet werden, nicht als Go-to-Sache.

JamesRyan
quelle
3

Ich habe in der Vergangenheit in einem 24x7-Fertigungsunternehmen mit einer sehr ähnlichen Situation gearbeitet und mich schließlich für die Transaktionsreplikation entschieden. Es ist möglich , DDL so zu konfigurieren, dass es repliziert wird, sodass Sie alle Änderungen der Patches auf den Abonnenten übertragen können. Offensichtlich gibt es für alles Vor- und Nachteile, und Sie müssen sie abwägen, um festzustellen, was Sie gegen das, was für das Unternehmen am besten funktioniert, unterstützen können.

Positiv ist, dass:

  1. "Echtzeit" ist nur auf die Netzwerk- und Transaktions-Commit-Leistung des Abonnenten beschränkt. Nach meiner Erfahrung mit einem System mit mäßig hohem TPS wurden wir innerhalb von weniger als 10 Sekunden auf "Echtzeit" -Daten repliziert.
  2. Trennung von Arbeitslasten. Sie führen derzeit eine gemischte Auslastung auf einem Server aus. Wenn Sie diese beiden Probleme trennen können, können Sie möglicherweise die Leistungsvorteile auf beiden Systemen erzielen, wenn Sie eine Arbeitslast aus der Gleichung entfernt haben
  3. Steuerung. Sie können Indexierungs-, Statistik- und Wartungsänderungen vornehmen, um sie an Ihre Berichterstellungs-Workload anzupassen.

Es gibt jedoch Nachteile:

  1. Kosten. Eine weitere Lizenz und mehr Hardware (virtuell oder anderweitig).
  2. Reproduzieren. Es funktioniert gut, wenn es richtig eingerichtet wurde, aber es kann mühsam sein, an diesen Punkt zu gelangen.
  3. Instandhaltung. Wenn Sie schädliche Änderungen an den Strukturen vornehmen (z. B. einen Index löschen), werden diese zurückgegeben, wenn der Snapshot angewendet wird (nachdem sich die Veröffentlichung geändert hat oder wenn sich die Artikel geändert haben).
Swasheck
quelle
2

Mein Plan war es, alle diese Datensätze in eine "Catch-All" -Tabelle zu schreiben und Trigger auf die Originaltabellen zu schreiben, um die Datensätze in dieser Aggregattabelle zu verwalten.

Trigger haben so viele Probleme, dass Sie sie vermeiden sollten:

  • Ein Fehler in einem Trigger kann zum Abbruch der ursprünglichen Transaktion führen
  • Trigger, die mehrzeilige Operationen korrekt verarbeiten, sind schwer zu schreiben
  • Trigger können Clientanwendungen verwirren, indem sie das zurückgegebene Rowset ändern (z. B. überschreibt ein Trigger die Anzahl der betroffenen Zeilen).
  • Wenn ein Trigger einen anderen auslöst, sind die Ergebnisse schwer vorherzusagen

Eine bessere Option ist ein Job, der die Daten regelmäßig in eine neue Tabelle kopiert. Ihre Berichte können von der Kopie ausgeführt werden. Ein Job, der Zeilen kopiert, ist einfach zu schreiben und zu warten, und es besteht kein Risiko, dass er den Betrieb der Drittanbieteranwendung beeinträchtigt.

Andomar
quelle
1. Die Auslöser wären einfach, so dass ausgelöste Fehler, wenn überhaupt, minimal wären. 2. Der Trigger selbst würde nicht mehrere Zeilen verarbeiten (dh eine mit dem Trigger in der Tabelle aktualisierte Zeile würde nicht dazu führen, dass mehrere Zeilen an einer anderen Stelle aktualisiert werden), es könnten jedoch mehrere Zeilen gleichzeitig in die Quelle eingefügt / aktualisiert / gelöscht werden Tisch - meinst du das? 3. Konnte das nicht gehandhabt werden NOCOUNT? 4. Es gäbe keine Auslöser auf der Zieltabelle, und ich könnte dasselbe für die anderen sicherstellen.
jreed121
Wie Sie sagen, ist es theoretisch möglich, Trigger zum Funktionieren zu bringen. Es ist nur so, dass sie es in der Praxis niemals tun.
Andomar