Es ist eine Idee, die ich an einigen Stellen wiederholt habe. Einige mehr oder weniger anerkennen, dass, wenn Sie versuchen, ein Problem nur in SQL zu lösen, ein gewisses Maß an Komplexität überschreiten, Sie es in der Tat in Code behandeln sollten.
Die Logik hinter der Idee ist, dass die Datenbank-Engine in den allermeisten Fällen die effizienteste Methode zur Ausführung Ihrer Aufgabe besser als im Code finden kann. Vor allem, wenn es darum geht, die Ergebnisse von Operationen abhängig zu machen, die an den Daten ausgeführt werden. Mit modernen Engines ist es wahrscheinlich sinnvoll, die kompilierte Version Ihrer Abfrage effektiv JIT-fähig zu machen und zwischenzuspeichern.
Die Frage ist, ob die Nutzung Ihrer Datenbank-Engine auf diese Weise von Natur aus eine schlechte Entwurfspraxis ist (und warum). Die Linien verschwimmen weiter, wenn die gesamte Logik in der Datenbank vorhanden ist und Sie sie nur über ein ORM treffen.
quelle
Antworten:
Mit den Worten des Laien:
Dies sind Dinge, für die SQL gemacht ist und die ich , ob Sie es glauben oder nicht, im Code gesehen habe:
Wenn Sie diese Dinge tun, anstatt sich auf SQL oder das RDBMS zu verlassen, schreiben Sie Tonnen von Code ohne Mehrwert , was bedeutet, dass Sie mehr Code debuggen und warten müssen. Und es wird gefährlich angenommen, dass auf die Datenbank nur über die Anwendung zugegriffen werden kann.
quelle
Ich würde das mit "Niemals in Code tun, was SQL Server für Sie gut kann " umformulieren .
Dinge wie String-Manipulation, Regex-Arbeit und so würde ich nicht in SQL Server (mit Ausnahme von SQL CLR) tun.
In den obigen Abschnitten wird in der Regel über Folgendes gesprochen: - Verknüpfungen, Festlegen von Vorgängen und Abfragen. Die Absicht dahinter ist viel von dem Heben schwerer Lasten auf SQL Server zu delegieren (an Dinge , die es ist gut) und die Menge an IO so weit wie möglich zu reduzieren (so SQL lassen Sie die Verknüpfungen und den Filter nach unten mit einer
WHERE
Klausel, eine viel Rückkehr kleinerer Datensatz als sonst).quelle
Der Schlüssel zur Antwort besteht darin, dass Sie sich darum bemühen müssen, dass SQL etwas für Sie gut macht, anstatt einfach etwas für Sie zu tun. SQL ist eine erstaunlich mächtige Sprache. In Verbindung mit integrierten Funktionen kann es möglicherweise viele Dinge bewirken. Die Tatsache, dass Sie etwas in SQL tun können, sollte jedoch keine Entschuldigung dafür sein, dies tatsächlich in SQL zu tun.
Meine spezifischen Kriterien für eine Entscheidung sind die Menge der zurückgegebenen Daten und die Anzahl der Roundtrips: Wenn Sie die Datenmenge durch Senden einer Aufgabe an den Server verringern können, ohne die Anzahl der Roundtrips zu erhöhen. löst aus, dann gehört die Aufgabe auf den Server; Wenn die Datenmenge gleich bleibt oder zunimmt, ohne dass gleichzeitig die Anzahl der Roundtrips abnimmt, gehört die Aufgabe in Ihren Code.
Betrachten Sie diese Beispiele:
quelle
WHERE
Klausel zu berechnen .Kurz gesagt wäre es richtig zu sagen: "Führen Sie niemals datenbankspezifische Operationen in Ihrer Codebasis durch", da diese in Ihrer Datenbank besser angesprochen werden.
Schauen Sie sich ein Beispiel für die festgelegten Basisoperationen an . Wie Sie vielleicht wissen, sind RDBMS so aufgebaut, dass sie allgemeine Datenspeicherungs- und -manipulationsvorgänge ausführen.
Darüber hinaus spielt die Projektauswahl der Datenbank eine wichtige Rolle . Ein RDBMS (MS SQL, Oracle usw.) zu haben, unterscheidet sich von NoSQL-Datenbanken wie RavenDB.
quelle
In der Regel verfügt Ihre Datenbank über mehr Informationen als Ihre Anwendung und kann allgemeine Datenvorgänge effizienter ausführen. In Ihrer Datenbank werden beispielsweise Indizes verwaltet, während Ihre Anwendung die Suchergebnisse sofort indizieren müsste. Wenn alle anderen Faktoren gleich sind, kann die Gesamtarbeitslast verringert werden, indem die Arbeit in die Datenbank und nicht in die Anwendung verschoben wird.
Mit der Skalierung Ihres Produkts wird es jedoch in der Regel einfacher, Ihre App als Ihre Datenbank zu skalieren. In großen Installationen ist es nicht ungewöhnlich, dass Anwendungsserver die Anzahl der Datenbankserver um den Faktor 10 zu 1 oder mehr übersteigen. Das Hinzufügen weiterer Anwendungsserver ist oft eine einfache Angelegenheit, um einen vorhandenen Server auf neue Hardware zu klonen. Das Hinzufügen neuer Datenbankserver ist dagegen in den meisten Fällen erheblich schwieriger.
An diesem Punkt wird das Mantra zum Schutz der Datenbank . Es stellt sich heraus, dass Sie durch das Zwischenspeichern der Datenbankergebnisse
memcached
oder durch das einmalige Abrufen der Daten und das Berechnen Ihrer Statistiken in Ihrer App die Arbeitslast Ihrer Datenbank drastisch reduzieren können, ohne auf diese zurückgreifen zu müssen eine noch kompliziertere und fragilere DB-Cluster-Konfiguration.quelle
Ich denke, es wäre ein schlechtes Design, die Datenbank nicht für die Dinge zu verwenden, für die sie gedacht ist. Ich habe noch nie eine Datenbank gesehen, in der die Regeln außerhalb der Datenbank mit guten Daten durchgesetzt wurden. Und ich habe mir Hunderte von Datenbanken angesehen.
Also Dinge, die in einer Datenbank erledigt werden müssen:
Überwachung (Nur-Anwendung-Überwachung verfolgt nicht alle Änderungen an der Datenbank und ist daher wertlos).
Dateningeritätsbeschränkungen, einschließlich Standardwerten, Fremdschlüsselbeschränkungen und Regeln, die immer auf alle Daten angewendet werden müssen. Es werden nicht immer alle Daten über eine Anwendung geändert oder eingefügt. Es gibt einmalige Datenkorrekturen, insbesondere für große Datensätze, die nicht einzeln durchgeführt werden können 2 aufgrund eines Anwendungscode-Fehlers sein oder bitte alle Datensätze von Client A auf Client B aktualisieren, da Firma B Firma A gekauft hat und Datenimporte und andere Anwendungen, die dieselbe Datenbank berühren könnten.
JOINS- und WHERE-Klausel-Filterung (um die Anzahl der über das Netzwerk gesendeten Datensätze zu verringern)
quelle
Die Datenbank ist genau das; die Datenschicht Ihrer Anwendung. Ihre Aufgabe ist es, Ihre Bewerbung mit den angeforderten Daten zu versorgen und die ihr übermittelten Daten zu speichern. In Ihrer Anwendung können Sie Code einfügen, der mit den Daten tatsächlich funktioniert. Anzeigen, Validieren usw.
Während die Stimmung in der Titelzeile bewundernswert und bis zu einem gewissen Punkt genau ist (das Wesentliche beim Filtern, Projizieren, Gruppieren usw. sollte in der überwältigenden Anzahl von Fällen der DB überlassen bleiben), könnte eine Definition von "gut" enthalten sein Bestellung. Es gibt viele Aufgaben, die SQL Server mit einer hohen Leistung ausführen kann, aber die Aufgaben, die Sie demonstrieren könnenEs gibt nur sehr wenige Fälle, in denen SQL Server auf isolierte, wiederholbare Weise korrekt arbeitet. SQL Management Studio ist eine großartige Datenbank-IDE (insbesondere in Anbetracht der anderen Optionen, mit denen ich wie TOAD gearbeitet habe), aber es hat seine Einschränkungen, zum einen ist es so ziemlich alles, wofür Sie es verwenden (oder jeden Prozedurcode, den Sie ausführen) Die darunter liegende DB ist per definitionem ein "Nebeneffekt" (Änderung des Zustands, der außerhalb der Domäne des Speicherbereichs Ihres Prozesses liegt). Darüber hinaus kann der prozedurale Code in SQL Server erst jetzt mit den neuesten IDEs und Tools anhand von Coverage-Metriken und Pfadanalysen auf die Art und Weise gemessen werden, wie verwalteter Code es kann (sodass Sie nachweisen können, dass Tests X auf diese besondere if-Anweisung stoßen) , Y und Z, und Test X soll die Bedingung erfüllen und diese Hälfte ausführen, während Y und Z das "else" ausführen . Dies setzt wiederum voraus, dass Sie über einen Test verfügen, mit dem die Datenbank mit einem bestimmten Startstatus eingerichtet, der Datenbankprozedurcode durch eine Aktion ausgeführt und die erwarteten Ergebnisse bestätigt werden können.
All dies ist viel schwieriger und komplizierter als die Lösung, die von den meisten Datenzugriffsschichten bereitgestellt wird. Nehmen Sie an, dass die Datenschicht (und im Übrigen die DAL) wissen, wie sie ihre Arbeit erledigen sollen, wenn sie die richtige Eingabe erhalten, und testen Sie dann, ob Ihr Code die richtige Eingabe liefert. Indem Sie prozeduralen Code wie SPs und Trigger aus der DB heraushalten und stattdessen diese Art von Dingen im Anwendungscode ausführen, ist der Anwendungscode viel einfacher zu üben.
quelle
Eines der Dinge, die die Leute nicht zu bemerken scheinen, ist, dass die gesamte Verarbeitung auf dem SQL-Server nicht unbedingt gut ist, unabhängig von den Auswirkungen auf die Codequalität.
Zum Beispiel, wenn Sie einige Daten erfassen und dann etwas aus den Daten berechnen und diese Daten dann in der Datenbank speichern müssen. Es gibt zwei Möglichkeiten:
Sie mögen denken, dass die zweite Lösung immer die schnellste ist, aber dies ist definitiv nicht wahr. Ich ignoriere, auch wenn SQL schlecht für das Problem geeignet ist (dh Regex und String-Manipulation). Nehmen wir an, Sie haben SQL CLR oder ähnliches, um sogar eine leistungsfähige Sprache in der Datenbank zu haben. Wenn es 1 Sekunde dauert, um einen Roundtrip durchzuführen und die Daten abzurufen, und 1 Sekunde, um sie zu speichern, und dann 10 Sekunden, um die Berechnung darüber auszuführen. Sie machen es falsch, wenn Sie alles in der Datenbank tun.
Klar, du rasierst dich 2 Sekunden ab. Hatten Sie jedoch lieber 10 Sekunden lang 100% (mindestens) eines CPU-Kerns auf Ihrem Datenbankserver verschwendet, oder hatten Sie diese Zeit lieber auf Ihrem Webserver verschwendet?
Webserver sind einfach zu skalieren, Datenbanken hingegen sind extrem teuer, insbesondere SQL-Datenbanken. In den meisten Fällen sind Webserver auch "zustandslos" und können nach Belieben hinzugefügt und entfernt werden, ohne dass eine zusätzliche Konfiguration für etwas anderes als den Load Balancer erforderlich ist.
Denken Sie also nicht nur daran, 2 Sekunden nach einer Operation zu sparen, sondern auch an die Skalierbarkeit. Warum sollten Sie eine teure Ressource wie Datenbankserverressourcen verschwenden, wenn Sie die viel billigeren Webserverressourcen mit einer relativ geringen Auswirkung auf die Leistung verwenden können?
quelle
Ich schaue es mir gerne an, da SQL nur mit den Daten selbst umgehen sollte. Die Geschäftsregeln, die entscheiden, wie die Abfrage aussehen kann, können im Code vorkommen. Die Regex oder Validierung der Informationen sollte in Code erfolgen. SQL sollte einfach in Ihre Tabelle aufgenommen, Ihre Daten abgefragt, saubere Daten eingefügt usw. werden.
Was an SQL übergeben wird, sollten saubere Daten sein und SQL sollte eigentlich nichts mehr wissen müssen, als dass es sie speichern, aktualisieren, löschen oder etwas abrufen muss. Ich habe viel zu viele Entwickler gesehen, die ihre Geschäftslogik und Codierung in SQL werfen möchten, weil sie die Daten als ihr Geschäft ansehen. Entkoppeln Sie Ihre Logik von Ihren Daten und Sie werden feststellen, dass Ihr Code sauberer und einfacher zu verwalten ist.
Nur meine 0,02 $.
quelle
Im Allgemeinen stimme ich zu, dass der Code die Geschäftslogik steuern sollte und die Datenbank ein logikfreier Hash sein sollte. Aber hier sind einige Gegenpunkte:
Primär-, Fremdschlüssel- und erforderliche (nicht null) Einschränkungen können durch Code erzwungen werden. Einschränkungen sind Geschäftslogik. Sollten sie aus der Datenbank herausgelassen werden, da sie duplizieren, was Code tun kann?
Berühren andere Parteien außerhalb Ihrer Kontrolle die Datenbank? In diesem Fall ist es hilfreich, Einschränkungen in der Nähe der Daten durchzusetzen. Der Zugriff kann auf einen Webdienst beschränkt werden, der Logik implementiert. Dies setzt jedoch voraus, dass Sie als "Erster" dort waren und die Befugnis haben, die Nutzung des Dienstes bei den anderen Parteien durchzusetzen.
Führt Ihr ORM für jedes Objekt ein separates Einfügen / Aktualisieren durch? Wenn ja, treten bei der Stapelverarbeitung großer Datenmengen schwerwiegende Leistungsprobleme auf. Set-Operationen sind der richtige Weg. Ein ORM wird Probleme haben, alle möglichen verbundenen Mengen, mit denen Sie Operationen ausführen könnten, genau zu modellieren.
Betrachten Sie eine "Ebene" als physische Aufteilung nach Servern oder als logische Aufteilung? Das Ausführen von Logik auf einem Server kann theoretisch immer noch unter die logische Ebene fallen. Sie können die Aufteilung organisieren, indem Sie in verschiedene DLLs kompilieren und nicht ausschließlich Server aufteilen. Dies kann die Reaktionszeit drastisch verlängern (aber den Durchsatz opfern), während die Trennung der Bedenken aufrechterhalten bleibt. Eine geteilte DLL kann später ohne einen neuen Build auf andere Server verschoben werden, um den Durchsatz zu erhöhen (auf Kosten der Antwortzeit).
quelle
Die Redewendung hat mehr damit zu tun, die Geschäftsregeln, die Daten und die Beziehungen (die Daten, die Struktur und die Beziehungen) beizubehalten. Es ist keine zentrale Anlaufstelle für jedes Problem, aber es hilft, Dinge wie manuell zu vermeiden gepflegte Datensatzzähler, manuell gepflegte Beziehungsintegrität usw., wenn diese Dinge auf Datenbankebene verfügbar sind. Wenn also jemand anderes hinzukommt und die Programme erweitert oder ein anderes Programm schreibt, das mit der Datenbank interagiert, muss er nicht herausfinden, wie die Datenbankintegrität aus dem vorherigen Code aufrechterhalten werden kann. Der Fall eines manuell gepflegten Datensatzzählers ist besonders relevant, wenn jemand anderes ein neues Programm erstellen möchte, um mit derselben Datenbank zu interagieren. Auch wenn das neu erstellte Programm genau den richtigen Code für den Zähler hat, Das ursprüngliche und das neue Programm, die ungefähr zur gleichen Zeit ausgeführt werden, können das Programm beschädigen. Es gibt sogar Code, der Datensätze abruft und Bedingungen überprüft, bevor ein neuer oder aktualisierter Datensatz geschrieben wird (im Code oder als separate Abfragen). Wenn möglich, kann dies häufig direkt in der Einfüge- oder Aktualisierungsanweisung erfolgen. Datenkorruption kann erneut zur Folge haben. Das Datenbankmodul garantiert die Atomizität. Eine Aktualisierungs- oder Einfügeabfrage mit Bedingungen wirkt sich garantiert nur auf die Datensätze aus, die die Bedingungen erfüllen, und keine externe Abfrage kann die Daten in der Hälfte des Aktualisierungszeitraums ändern. Es gibt viele andere Umstände, unter denen Code verwendet wird, wenn das Datenbankmodul besser funktioniert. Es geht um Datenintegrität und nicht um Leistung. Es gibt sogar Code, der Datensätze abruft und Bedingungen überprüft, bevor ein neuer oder aktualisierter Datensatz geschrieben wird (im Code oder als separate Abfragen). Dies kann, wenn möglich, häufig direkt in der Einfüge- oder Aktualisierungsanweisung erfolgen. Datenkorruption kann erneut zur Folge haben. Das Datenbankmodul garantiert die Atomizität. Eine Aktualisierungs- oder Einfügeabfrage mit Bedingungen wirkt sich garantiert nur auf die Datensätze aus, die die Bedingungen erfüllen, und keine externe Abfrage kann die Daten in der Hälfte des Aktualisierungszeitraums ändern. Es gibt viele andere Umstände, unter denen Code verwendet wird, wenn das Datenbankmodul besser funktioniert. Es geht um Datenintegrität und nicht um Leistung. Es gibt sogar Code, der Datensätze abruft und Bedingungen überprüft, bevor ein neuer oder aktualisierter Datensatz geschrieben wird (im Code oder als separate Abfragen). Dies kann, wenn möglich, häufig direkt in der Einfüge- oder Aktualisierungsanweisung erfolgen. Datenkorruption kann erneut zur Folge haben. Das Datenbankmodul garantiert die Atomizität. Eine Aktualisierungs- oder Einfügeabfrage mit Bedingungen wirkt sich garantiert nur auf die Datensätze aus, die die Bedingungen erfüllen, und keine externe Abfrage kann die Daten in der Mitte unseres Updates ändern. Es gibt viele andere Umstände, unter denen Code verwendet wird, wenn das Datenbankmodul besser funktioniert. Es geht um Datenintegrität und nicht um Leistung. Das Datenbankmodul garantiert die Atomizität. Eine Aktualisierungs- oder Einfügeabfrage mit Bedingungen wirkt sich garantiert nur auf die Datensätze aus, die die Bedingungen erfüllen, und keine externe Abfrage kann die Daten in der Mitte unseres Updates ändern. Es gibt viele andere Umstände, unter denen Code verwendet wird, wenn das Datenbankmodul besser funktioniert. Es geht um Datenintegrität und nicht um Leistung. Das Datenbankmodul garantiert die Atomizität. Eine Aktualisierungs- oder Einfügeabfrage mit Bedingungen wirkt sich garantiert nur auf die Datensätze aus, die die Bedingungen erfüllen, und keine externe Abfrage kann die Daten in der Mitte unseres Updates ändern. Es gibt viele andere Umstände, unter denen Code verwendet wird, wenn das Datenbankmodul besser funktioniert. Es geht um Datenintegrität und nicht um Leistung.
Es ist also eine gute Designsprache oder Faustregel. In einem System mit beschädigten Daten hilft keine Leistung.
quelle
Wie bereits erwähnt, ist es das Ziel, so wenig wie möglich aus der Datenbank zu senden und zu empfangen, da die Hin- und Rückflüge zeitaufwendig sind. Das wiederholte Senden von SQL-Anweisungen ist Zeitverschwendung, insbesondere bei komplexeren Abfragen.
Durch die Verwendung gespeicherter Prozeduren in der Datenbank können Entwickler mit der Datenbank wie mit einer API interagieren, ohne sich um das komplexe Schema auf der Rückseite kümmern zu müssen. Dies verringert auch die an den Server gesendeten Daten, da nur der Name und einige Parameter gesendet werden. In diesem Szenario kann der Großteil der Geschäftslogik noch im Code enthalten sein, jedoch nicht in Form von SQL. Der Code würde im Wesentlichen vorbereiten, was von der Datenbank gesendet oder angefordert werden soll.
quelle
Es gibt ein paar Dinge zu beachten:
quelle
Verwenden Sie das für den Job am besten geeignete Werkzeug. Aus Gründen der Datenintegrität ist dies häufig die Datenbank. Für erweiterte Geschäftsregeln ist dies ein regelbasiertes System wie JBoss Drools. Für die Datenvisualisierung wäre dies ein Berichtsrahmen. usw.
Wenn Sie Leistungsprobleme haben, sollten Sie anschließend prüfen, ob Daten zwischengespeichert werden können oder ob eine Implementierung in der Datenbank schneller wäre. Im Allgemeinen sind die Kosten für den Kauf zusätzlicher Server oder zusätzlicher Cloud-Leistung weitaus geringer als die zusätzlichen Wartungskosten und die Auswirkungen zusätzlicher Fehler.
quelle