Wann sollte ich gespeicherte Prozeduren verwenden?


19

Wenn ich meine gesamte Geschäftslogik im Code habe und Entity Framework verwende, in welchen Situationen (falls vorhanden) wäre es besser, eine Geschäftslogik in eine gespeicherte Prozedur zu verschieben, anstatt alles im Code zu belassen?

Um klar zu sein, meine ich in Verbindung mit dem aktuellen Setup (Geschäftslogik im Code) nicht statt. Ich habe eine Reihe ähnlicher Fragen gesehen, die nach den Vor- und Nachteilen einer vollständigen Geschäftslogik in gespeicherten Prozeduren fragen, aber ich habe nicht viel darüber herausgefunden, gespeicherte Prozeduren sparsam für die Edge-Case-Logik zu verwenden, während der Rest der Geschäftslogik beibehalten wird in Code.

Wenn es einen Unterschied macht, verwende ich MSSQL und Entity Framework.


Dies sind die Situationen, in denen ich zuvor gespeicherte Prozeduren verwendet habe:

  • Ein komplizierter Bericht, dessen Ausführung einige Minuten in Anspruch nahm (dies war eine Seite in einer Web-App). Ich fand heraus, dass ich SQL schreiben konnte, das viel effizienter war (nur wenige Sekunden) als das, was LINQ bereitstellte.
  • Eine Webanwendung musste einige Tabellen in einer separaten Datenbank lesen und in diese schreiben, die viele andere vertrauliche Informationen enthielt, die für die Anwendung nicht relevant waren. Anstatt ihm Zugriff auf alles zu gewähren, habe ich eine gespeicherte Prozedur verwendet, die nur das tut, was benötigt wird, und nur begrenzte Informationen zurückgibt. Die Webanwendung kann dann nur auf diese gespeicherte Prozedur zugreifen, ohne auf Tabellen usw. zuzugreifen.

Andere Posts, die ich mir angesehen habe, bevor ich diese Frage gestellt habe:


4
Beide Situationen sind absolut legitime Gründe für das Schreiben gespeicherter Prozeduren. Fragen Sie, warum sie legitim sind?
Robert Harvey

@RobertHarvey Ich habe mich vergewissert, dass sie legitim sind, und nach anderen Szenarien oder Gründen gesucht, warum Sie möglicherweise eine Ausnahme machen und eine gespeicherte Prozedur schreiben, anstatt sie im Code zu belassen.
Amy Barrett

Sie würden eine Ausnahme machen und eine gespeicherte Prozedur schreiben, wenn Sie feststellen, dass sie ein Problem besser löst als die anderen verfügbaren Techniken. Genau das haben Sie getan.
Robert Harvey

Antworten:


10

Sie haben bereits einige sehr gute Szenarien.

Es gibt auch viele andere Gründe. EF ist wirklich gut in CRUD und in der direkten Berichterstattung. Manchmal ist EF jedoch nicht das perfekte Werkzeug. Einige andere Gründe (Szenarien) für die Verwendung gespeicherter Prozeduren in Kombination mit Entity Framework sind:

  • Sie haben komplexe Arbeitseinheiten, an denen möglicherweise viele Tabellen beteiligt sind, die mit den Funktionen von EF nicht einfach in eine Transaktion eingebunden werden können.
  • Ihre Datenbank funktioniert mit EF nicht gut, da sie die deklarative referenzielle Integrität (Fremdschlüsseleinschränkungen) nicht nutzt. Dies ist normalerweise ein schlechtes Szenario, in dem Sie sich befinden. Manchmal gibt es jedoch auch geeignete Szenarien, z. B. Datenbanken, die für ETL-Prozesse verwendet werden.
  • Sie müssen mit Daten arbeiten, die Servergrenzen mit Verbindungsservern überschreiten.
  • Sie haben sehr komplexe Datenabrufszenarien, in denen "Bare-Metal" -SQL erforderlich ist, um eine angemessene Leistung sicherzustellen. Beispielsweise haben Sie komplexe Verknüpfungen, die Abfragetipps benötigen, um in Ihrer spezifischen Situation gut zu funktionieren.
  • Ihre Anwendung verfügt nicht über die vollständigen CRUD-Berechtigungen für eine Tabelle, kann jedoch in einem Sicherheitskontext ausgeführt werden, dem Ihr Server vertraut (z. B. Anwendungsidentität statt Benutzeridentität). Dies kann in Situationen auftreten, in denen DBAs den Tabellenzugriff auf gespeicherte Prozesse nur deshalb einschränken, weil sie eine genauere Kontrolle darüber haben, wer was tun kann.

Ich bin mir sicher, dass es noch viel mehr gibt. Der beste Weg, um unter bestimmten Umständen den richtigen Weg zu finden, besteht darin, einen gesunden Menschenverstand zu verwenden und sich auf das Hauptziel zu konzentrieren, nämlich qualitativ hochwertigen, leicht zu wartenden Code zu schreiben. Wählen Sie die Werkzeuge aus, die Ihnen in jedem Fall dieses Ergebnis liefern.


Danke Joel, Sie haben einige andere Szenarien erwähnt, an die ich nicht gedacht hatte.
Amy Barrett

Gute Antwort. Ich frage mich jedoch, ob Sie viele Benutzer haben, die mit der Datenbank verbunden sind und komplizierte Abfragen oder gespeicherte Prozeduren ausführen.
Ripal Barot

1
@RipalBarot Es steht außer Frage, dass die Anforderungen an Ihren Datenbankserver umso höher sind, je höher die Arbeitslast ist (mehr Benutzer, komplexere Abfragen). Beachten Sie jedoch, dass die Verwendung von gespeicherten Prozeduren anstelle von ORMs wie Entity Framework die Arbeitslast häufig (vergleichsweise) verringern kann, da gespeicherte Prozeduren vorkompilierte Abfragepläne haben können. Wenn eine Abfrage aus einem ORM stammt, muss das DBMS häufig zunächst herausfinden, wie mit der Abfrage umgegangen werden soll. Wenn Sie eine äquivalente gespeicherte Prozedur aufrufen, weiß die Datenbank bereits, wie sie effizient ausgeführt werden kann.
Joel Brown

2

Vielleicht ist es sinnvoll, die Frage umzudrehen und nach Anwendungsfällen zu suchen, in denen nur gespeicherte Prozeduren das tun können, was Sie erreichen möchten. Vielleicht gibt es wirklich Anwendungsfälle, in denen gespeicherte Prozeduren auffallen.

Wenn es einen Unterschied macht, verwende ich MSSQL und Entity Framework.

Mein Wissen über EF ist begrenzt, aber soweit ich sehen kann, ist EF ( nur ) ein ORM wie jeder andere. und ist glücklicherweise in der Lage, rohes SQL zu verwenden .

Wenn ich Ihre zwei Hauptpunkte nehme:

Ein komplizierter Bericht, dessen Ausführung einige Minuten in Anspruch nahm (dies war eine Seite in einer Web-App). Ich fand heraus, dass ich SQL schreiben konnte, das viel effizienter war (nur wenige Sekunden) als das, was LINQ bereitstellte.

LINQ / EF hat bei der Erstellung eines Berichts versagt. Und wie Sie bemerkt haben, war es SQLviel schneller als mit einem ORM. Aber spricht dies für gespeicherte Prozeduren oder nur gegen die Verwendung des ORM für alles?

Ihr Problem könnte offensichtlich mit SQL gelöst werden . Wenn diese Abfrage in Ihrer Codebasis gespeichert und versionskontrolliert wurde, macht dies - gemäß Ihrem Beispiel - zumindest keinen Unterschied .

Eine Webanwendung musste einige Tabellen in einer separaten Datenbank lesen und in diese schreiben, die viele andere vertrauliche Informationen enthielt, die für die Anwendung nicht relevant waren. Anstatt ihm Zugriff auf alles zu gewähren, habe ich eine gespeicherte Prozedur verwendet, die nur das tut, was benötigt wird, und nur begrenzte Informationen zurückgibt. Die Webanwendung kann dann nur auf diese gespeicherte Prozedur zugreifen, ohne auf Tabellen usw. zuzugreifen.

Gleiches hier: eine einfache Verbindungszeichenfolge und und UPDATE und dein Problem ist erledigt. Dieses Problem könnte sogar mit einem ORM gelöst werden : Verwenden Sie einfach einen Webservice vor der anderen DB und die gleiche Unterteilung / Isolation wird erreicht.

Also hier nichts zu sehen.

Blick auf einige Punkte, die andere gemacht haben:

Sie haben komplexe Arbeitseinheiten, an denen möglicherweise viele Tabellen beteiligt sind, die mit den Funktionen von EF nicht einfach in eine Transaktion eingebunden werden können.

Aber das SQLkann man machen. Hier geht es nicht um Magie .

Ihre Datenbank spielt nicht gut mit EF

Nochmals: Verwenden Sie gegebenenfalls EF .

Sie müssen mit Daten arbeiten, die Servergrenzen mit Verbindungsservern überschreiten

Ich sehe nicht, wie gespeicherte Prozeduren helfen. So kann ich nicht sehen einen Vorteil von gespeicherten Prozeduren; aber vielleicht bringt jemand etwas Licht ins Dunkel.

Sie haben sehr komplexe Datenabrufszenarien, in denen "Bare-Metal" -SQL erforderlich ist, um eine angemessene Leistung sicherzustellen

Nochmals: "Grenzen von EF ".

Ihre Anwendung verfügt nicht über die vollständigen CRUD-Berechtigungen für eine Tabelle, kann jedoch in einem Sicherheitskontext ausgeführt werden, dem Ihr Server vertraut

Okay. Ich gehe mit einem vielleicht .

Bisher wurde nur ein halber Punkt für gespeicherte Prozeduren gemacht.


Möglicherweise gibt es Leistungsüberlegungen, die für gespeicherte Prozeduren sprechen.

1) Das Speichern von Abfragen bietet den Vorteil eines einfachen Aufrufs der gespeicherten Prozedur, der die Komplexität zusammenfasst. Da der Abfrageplaner die Abfrage kennt, ist die Optimierung "einfacher". Aber die Speicher sind mit dem aktuellen hochentwickelten Abfrageplaner _minimal.

Darüber hinaus ist die Datenbank selbst bei geringen Kosten für Ad-hoc- Abfragen, wenn Ihre Daten gut strukturiert und sorgfältig indiziert sind, lediglich der Engpass Ihrer Anwendung. Selbst wenn es ein kleines Delta gibt, ist es unter Berücksichtigung anderer Faktoren vernachlässigbar.

2) Trotzdem wurde argumentiert, komplexe Abfragen in einer DB zu speichern . Es gibt zwei Dinge zu beachten:

a) Komplexe Abfragen nutzen massiv die DB-Infrastruktur, was die Antwortzeiten für jede andere Abfrage erhöht. Sie können nicht viele laufen teure Abfragen in parallel . Das spricht weder pro noch contra gespeicherte Prozeduren, sondern gegen komplexe Abfragen.

b) Wenn die Abfrage trotzdem einige Zeit in Anspruch nimmt, warum stört es Sieger einer gespeicherten Prozedur mit geringer Geschwindigkeit?

tl; dr

Nichts spricht direkt gegen gespeicherte Prozeduren. Die Verwendung gespeicherter Prozeduren ist also in Ordnung - wenn es Sie glücklich macht.

Aber auf der anderen Seite: Ich konnte mir keinen richtigen Anwendungsfall vorstellen, der eindeutig pro spricht .

Wann sollte ich gespeicherte Prozeduren verwenden?

Die richtige Antwort lautet: Wann immer Sie möchten . Es gibt aber auch andere Möglichkeiten.


0

Da Sie das Entitätsframework verwenden, sollten Sie für Ihren speziellen Fall die Verwendung gespeicherter Prozeduren in Betracht ziehen, wenn das Entitätsframework eine Anforderung oder ein Anliegen nicht erfüllt.

Das Entity-Framework leistet gute Arbeit und die Leistung entspricht in etwa der Verwendung gespeicherter Prozeduren. Sie haben das Entity-Framework ausgewählt, weil Sie sich nicht mit SQL befassen wollten und das Framework das SQL für Sie generieren lässt.

Es kann jedoch einen Randfall geben, bei dem das Entity-Framework nicht ausreichend ist und Ihre Anforderungen nicht erfüllt. In diesem Fall würde man das SQL von Hand mit einer gespeicherten Prozedur oder einer parametrisierten Abfrage schreiben und dann das Entity-Framework verwenden, um diese gespeicherte Prozedur / SQL-Anweisung direkt aufzurufen.

Daher würde ich nichts in eine gespeicherte Prozedur verschieben, es sei denn, das verwendete Framework kann die Anforderung nicht erfüllen.

Ich denke, das Schlimmste, was passieren kann, ist, dass man das Entity-Framework verwendet und dann alle gespeicherten Prozeduren schreibt. Jetzt hat man eine zusätzliche Ebene, die keinen Wert hinzufügt.


100% stimmen mit dem letzten Absatz überein
Ewan

0

Ein technisches Bedürfnis zu haben, ist nicht die wahrscheinlichste Wahl. Programmierer bevorzugen ihre Werkzeuge und sind in der Regel besser in der Lage, ihre Probleme mit ihnen zu lösen. Das Einfügen von Logik in einen Sproc ist die Ausnahme. Technische Schulden und zukünftige Entwickler, die sich Zeit nehmen müssen, um mit einer Ausnahme zu arbeiten, sollten in Betracht gezogen werden. In Ihrem speziellen RDBMS kann es zu einer Leistungssteigerung kommen, die sich in einem Sproc oder sogar einem anderen Datenbankobjekt wie einer indizierten Sicht einfacher implementieren lässt.

Es wird Zeiten geben, in denen Sie Daten aus einer Datenbank benötigen und diese einfach nicht aus Ihrem Anwendungscode abrufen können. In vielen Situationen großer Unternehmen können die Geschäftsanforderungen die Reichweite der IT-Abteilung übersteigen. Unternehmen werden gekauft und verkauft und ihre Anwendungen kommen und gehen mit ihnen. Aufsichtsbehörden und Banken kümmern sich nicht darum, ob Sie Ihre hochskalierbare und schön codierte App nicht erstellen können. Sie können dem Geschäft das Leben schwer machen, also müssen Sie es erledigen.

Ich habe Situationen erlebt, in denen Drittanbieteranwendungen oder Berichterstellungstools nicht zulassen, dass Sie an Ihren Code gelangen. Kein Open Source Code, keine API, kein Webinterface und keine Services. Das einzige, was sie haben, ist ein spezielles Tool zum Schreiben von Berichten, das nur mit Datenbankobjekten funktioniert: Tabellen, Ansichten, Sprocs, benutzerdefinierte Funktionen usw. Sie platzieren die Logik dort, wo Sie sie haben.

Wenn Sie über einen Datenbankadministrator verfügen, der das Schreiben gespeicherter Prozeduren sehr gut beherrscht, können Sie dieses Talent in bestimmten Situationen nutzen. Möglicherweise möchten Sie eine Sicherung Ihrer App auslösen, weil Sie eine wesentliche Datenänderung vornehmen werden. Warum also nicht das verwenden, was Ihre DBA verwendet?

Bei einigen Ad-hoc-Anfragen ist es nur einfacher, einen Prozess zu schreiben, bis Sie alle Funktionen in Ihrer App erhalten. Wir hassen es. Wir drängen zurück, aber die Show muss weitergehen.


0

Ich würde dringend davon abraten, Geschäftslogik in eine gespeicherte Prozedur einzufügen. Es kann jedoch einen Fall geben (Sie haben zwei gute Beispiele aufgeführt), in dem es vorzuziehen ist, dort Datenzugriffslogik zu platzieren .

Wenn Sie versucht sind, SPs zu verwenden, ist dies im Allgemeinen ein Zeichen (ein Codegeruch), das darauf hinweist, dass Ihr Datenmodell nicht gut für seine Anforderungen geeignet ist.

Bearbeiten: Wenn Entwickler mich nach der Geschäfts- / Datenzugriffslogik fragen, geht es bei der Geschäftslogik um das Verhalten und die Interaktion von Daten, während es bei der Datenzugriffslogik darum geht, wie Daten gespeichert und abgerufen werden.

Zum Beispiel: In Ihrem Domain-Modell haben Sie möglicherweise die Entitäten "Student" und "Teacher", die beide von "Person" abgeleitet sind. (Das nicht zu sagen ist bevorzugt, nur ein Beispiel). Dies kann in einer relationalen Datenbank als eine, zwei oder drei Tabellen gespeichert werden. Die Auswahl hängt davon ab, wie viele Eigenschaften sie gemeinsam nutzen und welche Anforderungen an die Lese- / Schreibleistung gestellt werden.

In der Geschäftslogik sollte es keine Rolle spielen, wie diese Entitäten gespeichert werden. (oder ob sie sich überhaupt in einer RDB befinden). Bei der Datenzugriffslogik geht es darum, wie sie physisch gespeichert werden.

Bezüglich der ursprünglichen Frage: Wenn eine gespeicherte Prozedur das Speichern und Abrufen von Daten effizienter (oder zuverlässiger) macht, haben Sie einen Fall. Wenn die gespeicherte Prozedur lediglich zum Auferlegen einer Regel dient, die unabhängig von der Art der Speicherung von Daten gültig ist, vermeiden Sie sie. Dadurch wird Ihr Code enger an die Datenbank gekoppelt.


2
Wie würden Sie Geschäftslogik und Datenzugriffslogik definieren?
Amy Barrett


@RobertHarvey Danke für die Links. Ist die Datenzugriffsschicht dieselbe wie die Datenzugriffslogik? Ich frage, da die Datenzugriffsschicht anscheinend nicht viel Logik enthält - nur einfache CRUD-Operationen.
Amy Barrett

@ AmyBarrett: Nun, manchmal schreibt man benutzerdefinierte Methoden in die Datenzugriffsebene, so dass es nicht immer CRUD ist.
Robert Harvey

@RobertHarvey Gehören diese benutzerdefinierten Methoden nicht in die Geschäftslogikebene?
Amy Barrett

-4

Ich denke, hier gibt es drei Probleme.

  1. Geschäftslogik in SQL ist schlecht. Auch wenn es individuell schneller läuft, skaliert es nicht.

  2. Traditionell sollten SPROCs immer für den gesamten Datenzugriff als Abstraktionsschicht verwendet werden. Aktivieren eines DBAs, um die Leistung oder andere Änderungen der Datenschicht einzuführen, ohne die verbrauchenden Anwendungen zu beeinträchtigen.

  3. EF spielt nicht gut mit Sprocs. Sie werden viele der "guten" Funktionen und Produktivitätssteigerungen verlieren, wenn Sie von der dynamischen Abfragegenerierung von Linq weggehen.

Mein genereller Rat wäre also:

  • Verwenden Sie SPROCs für alle SQL-Abfragen,

  • Fügen Sie keine Geschäftslogik oder Schleifen ein.

  • Verwenden Sie nicht EF.


Da alle SQL-Anweisungen auf dem Datenbankserver ausgeführt werden, können Sie nur mit zusätzlichen Datenbanken und nicht mit zusätzlichen Rechenfeldern skalieren.
Ewan

1
Aha. Aber Punkt 1 handelt nur von einem Kompromiss zwischen zwei Leistungsproblemen. Aber es wird Zeiten geben, in denen die SQL-Lösung in Bezug auf die Leistung einen deutlichen Gewinn darstellt. Daher sehe ich nicht, wie sie auf dieser Grundlage als kategorisch "schlecht" eingestuft werden kann.

1
Angenommen, Sie haben einen Webservice, der eine Berechnung durchführt. Sie können es im Code oder in der SQL tun. Sagen wir, die SQL ist schneller in einem Kopf-an-Kopf-Test einer einzelnen Berechnung. Aber wenn der Service voll ist CPU ist es sehr billig und einfach, ein zweites, drittes, viertes hinzuzufügen. Box, auf der der Webservice läuft, aber schwer und teuer, eine zweite replizierte Datenbank hinzuzufügen
Ewan

1
Dies ist ein Beispiel für ein bestimmtes Szenario, in dem SQL aufgrund der Skalierbarkeit möglicherweise ein schlechtes Design aufweist. Aber selbst dann ist es nicht klar: Es hängt von der erwarteten Anzahl der Benutzer, den relativen Kosten für die Ausführung der Berechnung in der Datenbank im Vergleich zu außerhalb usw. ab. Natürlich haben Sie in einigen Fällen recht, ich glaube einfach nicht, dass es eine universelle Regel ist.

3
Dies ist insgesamt ein schlechter Rat. Es gibt viele Optionen für den Datenzugriff, die Vorteile gegenüber der Handcodierung gespeicherter Prozeduren haben und genau so gut funktionieren. Sie können Sprocs direkt von EF ausführen. Tatsächlich können Sie jede SQL-Abfrage direkt von EF aus ausführen. Einige Geschäftslogiken laufen auf einem Datenbankserver besser, sodass Sie nicht eindeutig angeben können, dass sie dort verboten sind. Objektrelationale Mapper sind zu 80% ein Werkzeug. Sie sollten niemals Ihre Datenzugriffsprozesse vollständig ersetzen. Verwenden Sie gespeicherte Prozeduren für das, wofür sie vorgesehen sind: die 20%, die ein ORM nicht gut macht.
Robert Harvey
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.