"Machen Sie in Code niemals das, was der SQL Server für Sie tun kann." - Ist dies ein Rezept für ein schlechtes Design?


204

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.


60
Dies ist eine dieser Redewendungen, die nachdenklich aufgenommen werden muss. Es wird ausgeblendet, wenn ein anderer Bearbeiter "select * from table" ausführt und dann die Ergebnismenge durchsucht, anstatt eine where-Klausel zu verwenden und Spalten anzugeben. Aber wenn Sie zu weit gehen, haben Sie ein anderes Durcheinander.
Michael Kohne

154
Das Beginnen einer Phrase mit "nie" oder "immer" ist fast immer ein Rezept für ein schlechtes Design.
vsz

34
Obwohl es sicherlich möglich ist , zu viel in SQL zu tun, kann ich ehrlich sagen, dass ich in 30 Jahren Entwicklung und Beratung noch nie einen ernsthaften Fall davon gesehen habe (ein paar kleinere). Andererseits habe ich buchstäblich Hunderte schwerwiegender Fälle von Entwicklern gesehen, die versucht haben, im "Code" zu viel zu tun, was sie in SQL hätten tun sollen. Und ich sehe sie immer noch. Häufig ...
RBarryYoung

2
@MrEdmundo Bring es zu Meta.
ta.speot.is

4
Diese Frage ist zwei in einem - ich denke, es sollte geteilt werden. 1) Wie viel sollte in SQL getan werden? 2) Wie viel sollte im DBMS getan werden? Gespeicherte Prozeduren liegen in der Mitte. Ich habe ganze Anwendungen gesehen, die in gespeicherten Prozeduren codiert sind.
reinierpost 24.10.12

Antworten:


321

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:

  • Joins - Codeweise würde es komplexe Array-Manipulation erfordern
  • Filtern von Daten (wo) - Codeweise würde es ein umfangreiches Einfügen und Löschen von Elementen in Listen erfordern
  • Spalten auswählen - codeweise würde es eine umfangreiche Listen- oder Array-Manipulation erfordern
  • Aggregatfunktionen - Codeweise würde es Arrays erfordern, um Werte und komplexe Schalterfälle zu speichern
  • Fremdschlüsselintegrität - Codemäßig sind vor dem Einfügen Abfragen erforderlich, und es wird davon ausgegangen, dass niemand die Daten außerhalb der App verwendet
  • Primärschlüsselintegrität - Codemäßig sind vor dem Einfügen Abfragen erforderlich, und es wird davon ausgegangen, dass niemand die Daten außerhalb der App verwendet

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.


88
+10000000000 für den Hinweis, dass gefährlich angenommen wird, dass alles nur durch die Anwendung geschehen wird.
HLGEM

11
@skynorth Es führt zu einem schlechten Datenbankdesign. In der Folge haben Sie eine Datenbank, auf die diese Anwendung aufgrund der Nachbearbeitung nur sinnvoll zugreifen kann .
Sirex

21
@skynorth Wenn Sie sich auf den Code verlassen, um die Integrität Ihrer Schlüssel zu gewährleisten, entfernen Sie ein grundlegendes Prinzip von RDBMS aus der Datenbank. Das macht keinen Sinn, denn dann muss jede Anwendung, die auf die Datenbank zugreift, sicherstellen, dass diese Funktionalität präzise repliziert wird. Warum nicht einfach die DB damit umgehen lassen, denn dafür ist sie konzipiert. Die DB kann beispielsweise doppelte Schlüssel von Haus aus verhindern.
Buttle Butkus

10
Vergiss die Transaktionen nicht!
Sklivvz

24
@skynorth: tl; dr: Die Regeln, die Ihre Daten konsistent halten, sollten in der Datenbank implementiert werden. dh für 99% der Anträge je geschrieben wurden , werden die Daten (und damit die Datenbank) lebt looooooooooong nach Ihrer Anwendung ist tot und vergangen. Ich habe das viele Male in den letzten Jahren gesehen (Hey, wir müssen eine Version auf Windows / iPhone / Android / was-auch-das-Neue-ist-bereitstellen, weil {alte Plattform hier einfügen} im Sterben liegt, wir ' ll Host oder Oracle - Datenbank hier und erstellen Sie eine neue UI dort ). Es gibt keinen Grund, warum dieser Trend heute oder in naher Zukunft aufhören sollte.
Binary Worrier

122

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 WHEREKlausel, eine viel Rückkehr kleinerer Datensatz als sonst).


27
Wenn alles, was SQL besser machen würde als App-Code, in die SQL-Ebene gestellt würde, stünde eine Menge Geschäftslogik in der Datenbank. Ich habe das gesehen und ja, die Leistung war hervorragend. Glücklicherweise kannte sich das Entwicklerteam mit App-Entwicklung und SQL bestens aus, da die Grenze zwischen beiden sehr amorph wurde. Ich würde dies nicht als Ausgangspunkt, sondern als Endpunkt vorschlagen, nachdem das System enorm populär geworden ist und die Leistung mit der Zeit abnimmt.
Jimmy Hoffa

3
Pferde für Kurse ohne GuV?
StuperUser

28
@ NathanLong Ich weiß nicht, warum so viele Leute immer noch denken, dass Sie Ihr SQL nicht in der Quellcodeverwaltung behalten können. Zuerst hatten wir nur alle unsere gespeicherten Prozeduren / Tabellenskripte / etc, die zum Erstellen der Datenbank von Grund auf in der Quellcodeverwaltung erforderlich waren, und später verwendeten wir Visual Studio-Datenbankprojekte. Ohne die Projekte hat es gut geklappt und mit ihnen besser. SQL sollte wie jedes andere veränderbare Element, das für die Erstellung Ihres Systems erforderlich ist, unter Versionskontrolle stehen! Die Bereitstellung kann mit Redgate Diff-Tools für die meisten RDBMS erfolgen, wenn Sie Ihre Erstellungsskripte unter Versionskontrolle halten und keine Diff-Skripte mit Tools verwalten
Jimmy Hoffa,

3
Wenn Ihr SQL-Code REGEX-Operationen und Zeichenfolgenmanipulationen unterstützt, kann es eine gute Wahl sein, diese in SQL auszuführen.
Kevin Cline

3
@ NathanLong: Stellen Sie sich das so vor: Eine DB-Tabelle wird durch einen Codeabschnitt definiert, der in einer Textdatei geschrieben ist. Die Syntax entspricht der von "Tabelle erstellen ...". Jetzt können Sie diese Textdatei in einem beliebigen SCM speichern, genau wie wenn Sie DB-Tabellenerstellungscode in Ihrer bevorzugten Anwendungssprache haben, der die erforderliche API aufruft, und diese Textdatei in Ihrem SCM speichern. Ich denke, das Problem ist, dass einige Leute denken, DBs sind irgendwie magische Bestien, und sie wissen nur, wie man VB-Code schreibt (oder was auch immer) und sie denken nur in Bezug auf die Anwendungssprache, die sie kennen.
gbjbaanb

47

Mach niemals im Code, was der SQL Server für dich gut machen kann (Betonung liegt bei mir)

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:

  • Sie speichern ein Geburtsdatum und müssen das Alter für eine Gruppe von Benutzern berechnen. Sie können SQL Server die Subtraktion ausführen lassen, oder Sie können es in Ihrem Code ausführen. Die Anzahl der Hin- und Rückflüge bleibt gleich, und die an Sie zurückgesendete Datenmenge steigt. Daher gewinnt eine codebasierte Lösung
  • Sie speichern ein Geburtsdatum und müssen Benutzer im Alter zwischen 20 und 30 Jahren finden. Sie können alle Benutzer wieder auf den Client laden, das Alter subtrahieren und dann filtern, aber die Logik an SQL Server senden würde die Datenmenge reduzieren, ohne dass zusätzliche Hin- und Rückflüge erforderlich wären; Daher gewinnt eine SQL-basierte Lösung.

1
Als ich irgendwo arbeitete, wurde die Geschäftslogik mit SQL amorph, und wir hatten keine Probleme mit mehreren Roundtrips. Wir haben nur mehrere Ergebnismengen in einer einzelnen Rundreise verwendet, sodass die Regel dort irgendwie zusammenbricht, obwohl der Geist der Regel ziemlich gut darin ist, den goldenen Mittelwert anzustreben
Jimmy Hoffa,

2
+1 das ist eine fantastische Antwort, weil es konkrete Beispiele gibt, um beide Richtungen zu unterstützen.
Brandon

1
Bei Ihrem zweiten Beispiel. Was sagen Sie, wenn das Szenario wie folgt ist? Die Benutzer und Bday sind Caches und sagen, dass die Datensatzgröße im Bereich von 1000-2000 liegt. Ist dies nicht schneller, um dies im Speicher zu erledigen? Kein DB-Aufruf erforderlich, da die Daten zwischengespeichert werden, und so wird die SQL-Operation "dazwischen" vermieden. Die Verarbeitung wird durch eine Liste von über 1000 Benutzern im Speicher iteriert und es wird ermittelt, wo die Übereinstimmung auftritt. Wird das nicht schneller sein als das in db
user4677228

1
@ user4677228 Aber versuchen Sie es mit einer Vergrößerung :-p. Wenn Ihr Code alle Daten scannen muss, um alle Altersstufen zu berechnen, und Ihr gewünschtes Ergebnis lautet "Wie viele Benutzer sind mindestens 20 und jünger als 30?", Helfen Ihnen die Caches überhaupt nicht. Sie werden am Ende immer noch die gesamte Tabelle an Ihren Client streamen, aber der Datenbankserver könnte dies alles in seinem Speicher / Cache tun und Ihnen eine schnelle Antwort geben, unabhängig davon, ob der DB-Client eine Verbindung über lokale Sockets oder remote über das Netzwerk herstellt, wenn Sie sind nur bereit, das Alter in einer WHEREKlausel zu berechnen .
Binki

21

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.


Niemals festgelegte Operationen in Ihre Codebasis aufzunehmen, würde bedeuten, dass absolut alles, was in LINQ für Sammlungen (select, sum, where, single) ausgeführt wird, in SQL ausgeführt werden sollte und nicht in Ihrer App. Dies würde VIELE Geschäftslogik in Ihre Datenbank aufnehmen.
Jimmy Hoffa

4
Die Dinge, die Sie beschreiben, sind kein Client-Code. Es ist eine Business-Schicht, in der Sie möglicherweise Ihre eigene Manipulationslogik haben. Das Durchführen dieser Logik bei 1M + -Datensätzen wird Sie jedoch zurückschlagen.
EL Yusubov

@JimmyHoffa: Das stimmt nicht, manchmal generieren Sie vorübergehende Informationen, die mit den Daten verarbeitet werden müssen, die sich bereits im App-Speicher befinden. Daran wirkt Linq Wunder.
Fabricio Araujo

@FabricioAraujo Mir ist bewusst, warum Linq großartig ist, aber in dieser Antwort heißt es: Niemals festgelegte Vorgänge in App-Code ausführen. Wenn Sie niemals Vorgänge in App-Code ausführen, würden Sie Linq niemals verwenden, da dies der gesamte Zweck von Linq ist. Ich mache den Punkt, dass es eine schlechte Regel ist , niemals festgelegte Operationen im App-Code auszuführen
Jimmy Hoffa

@JimmyHoffa: Nein, die Regel besagt "Mach niemals in der App, was das RDBMS für dich gut kann". Und ich spreche von vorübergehenden Informationen - nicht von Informationen, die in der Datenbank gespeichert sind. Ich habe an Systemen gearbeitet, auf denen ich zur Erfüllung der Geschäftsregeln Code verarbeiten musste. Ich erinnere mich an eine Geschäftsregel, die ich nach intensiver Verarbeitung in der Datenbank für diese Daten zusätzlich verarbeiten musste, um einen (sehr wichtigen) Bericht zu erstellen. Ich was ich verwenden könnte Linq auf das (es wurde auf der jetzt nicht mehr existierenden Delphi.Net getan). Mit anderen Worten, linq kann auch nach dieser Regel verwendet werden.
Fabricio Araujo

13

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 memcachedoder 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.


1
Geld kann Probleme mit der Hardware-Skalierbarkeit lösen, wohingegen kein Geldbetrag die Komplexität der Software lösen kann.
Tulains Córdova

3
@ user1598390 In der Tat: Hardware ist billig, Programmierer sind teuer . Geld kann Softwarekomplexität lösen. Geld für Programmierer. Beachten Sie jedoch, dass es nicht um sauberen Code im Vergleich zu Speghetti geht. Wir sprechen über die Ausführung von Arbeiten auf der App-Seite im Vergleich zur DB-Seite. Die Komplexität der Software ist nur am Rande miteinander verbunden, da beide Optionen guten Entwurfsprinzipien folgen können. Eine bessere Frage ist: " Welches Design kostet mehr? ".
TylerL

Sobald Sie eine Codebasis haben, die riesig und fett ist, und die meisten nicht-geschäftlichen Aufgaben erledigt, können Sie nur die Mutter aller Re-Engineerings ausführen, die mehr kosten als Hardware und außerdem zu viel Unsicherheit mit sich bringen Sie werden immer wissen, wo Sie gute Hardware finden, aber gute Programmierer sind eine andere Geschichte. Währenddessen nutzen Ihre Konkurrenten ihre Zeit, um sich zu verbessern, sich an Veränderungen anzupassen und Kunden glücklich zu machen.
Tulains Córdova

1
+1 für die einzige Person, die die Skalierung in Ihrer Antwort erwähnt.
Matt

Hardware war nicht mehr billig - im Rechenzentrum machen Strom und Hardware 88% der laufenden Kosten aus (wie von Microsoft angegeben), sodass höhere Ausgaben für Programmierer, um effizienten Code zu schreiben, sehr kosteneffektiv sind und so lange dauern, bis wir unbegrenzt und verfügbar sind billige Fusionskraft.
gbjbaanb

12

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)


6

"Vorzeitige Optimierung ist die Wurzel allen Übels (das meiste jedenfalls) in der Computerprogrammierung" - Donald Knuth

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.


Warte, warte, was? Wie sind Sie von Korrektheitsnachweisen zu Tests gekommen, die beweisen können, dass Fehler existieren, aber niemals beweisen können, dass der Code korrekt ist?
Mason Wheeler

2
Eine gespeicherte Prozedur ist kein Prozedurcode. Ein SP ist eine vorberechnete SQL-Abfrage, die in der Datenbank gespeichert und ausgeführt wird. Es ist kein Anwendungscode.
gbjbaanb

1
Wenn der SP auf eine SQL-Abfrage beschränkt ist, haben Sie Recht. Wenn es sich um T-SQL oder PL / SQL handelt, einschließlich bedingter Unterbrechungen, Schleifen, Cursor und / oder anderer Nicht-Abfrage-Logik, liegen Sie falsch. Viele SPs, Funktionen und Trigger in DBs im gesamten Cyberspace enthalten diese zusätzlichen Elemente.
KeithS

5

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:

  • Nehmen Sie die Daten in Ihre Anwendung auf, berechnen Sie sie in Ihrer Anwendung und senden Sie sie dann an die Datenbank zurück
  • Erstellen Sie eine gespeicherte Prozedur oder Ähnliches, um die Daten zu erfassen, sie zu verarbeiten und anschließend von einem einzigen Aufruf an SQL Server zu speichern.

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?


1
Sie vergessen auch Netzwerkausflüge - Sie können nicht horizontal skalieren, indem Sie Server hinzufügen, ohne die Effizienz zu beeinträchtigen. Das Reduzieren der Datenlast durch Hinzufügen einer where-Klausel liegt auf der Hand - die anderen sql-Operationen reduzieren jedoch nicht unbedingt die Leistung. Ihr Punkt ist zwar im Allgemeinen korrekt, aber nicht bis zu dem Punkt, an dem Sie die DB als dummen Datenspeicher behandeln. Die skalierbarste App, an der ich je gearbeitet habe, verwendete gespeicherte Prozeduren für jeden Datenaufruf (mit Ausnahme von 2 komplexen Abfragen). Eine dritte Lösung ist die beste - "gespeicherte Prozedur, um nur die erforderlichen Daten zu erfassen", nicht sicher, ob Sie das als "Berechnen" bezeichnet haben oder nicht.
gbjbaanb

4

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 $.


Warum sollten Sie einen regulären Ausdruck oder eine Validierung für Daten ausführen, die sich bereits in der Datenbank befinden? Einschränkungen sollten verhindern, dass schlechte Daten jemals dort ankommen, und die Verwendung von Regex bedeutet wahrscheinlich, dass Sie nützlichere Spalten benötigen.
Brendan Long

Ich habe nicht gesagt, dass ich Regex oder Validierung für Daten verwenden würde, die aus der Datenbank stammen. Ich denke, ich hätte klären sollen, dass Daten in die Datenbank gelangen. Mein Punkt dort war, dass die Daten gesäubert und validiert werden sollten, bevor sie zum DAL gelangen.
Stanley Glass Jr

3

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).


Warum die Gegenstimme?
mike30

5
Ich habe nicht abgelehnt, aber jeder Datenbank-Spezialist wird Ihnen sagen, dass es eine sehr schlechte Idee ist, die Datenbank als logikfreien Hash zu betrachten. Es verursacht Datenintegritätsprobleme oder Leistungsprobleme oder beides.
HLGEM

1
@HLGEM. In der Antwort werden Gründe beschrieben, warum die Logik in der Datenbank verbleibt oder auf dem DB-Server gespeichert wird. Erklärt es immer noch nicht.
mike30

Sie sind vielleicht nicht so weit gekommen wie ich, weshalb ich nicht abgestimmt habe.
HLGEM

3

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.


0

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.


0

Es gibt ein paar Dinge zu beachten:

  • Eine relationale Datenbank sollte die referenzielle Integrität durch Fremdschlüssel sicherstellen
  • Das Skalieren einer Datenbank kann schwierig und teuer sein. Das Skalieren eines Webservers ist viel einfacher, wenn Sie einfach weitere Webserver hinzufügen. Viel Spaß beim Hinzufügen von mehr SQL Server-Leistung.
  • Mit C # und LINQ können Sie Ihre "Joins" und so weiter durch Code ausführen, sodass Sie in vielen Fällen das Beste aus beiden Welten herausholen

0

"Vorzeitige Optimierung ist die Wurzel allen Übels" - Donald Knuth

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.