Frage

Angenommen, Sie können LINQ aus irgendeinem Grund nicht verwenden: Ist es eine bessere Vorgehensweise, Ihre Abfragen in gespeicherten Prozeduren zu platzieren, oder ist die Ausführung genauso sinnvoll? ad hoc Abfragen gegen die Datenbank (z. B. SQL Server zur Argumentation)?

War es hilfreich?

Lösung

Aufgrund meiner Erfahrung beim Schreiben hauptsächlich von WinForms-Client/Server-Apps bin ich zu folgenden einfachen Schlussfolgerungen gekommen:

Verwenden Sie gespeicherte Prozeduren:

  1. Für jede komplexe Datenarbeit.Wenn Sie etwas tun möchten, das wirklich einen Cursor oder temporäre Tabellen erfordert, ist es normalerweise am schnellsten, dies innerhalb von SQL Server zu tun.
  2. Wenn Sie den Zugriff auf die Daten sperren müssen.Wenn Sie Benutzern (oder Rollen oder was auch immer) keinen Tabellenzugriff gewähren, können Sie sicher sein, dass die einzige Möglichkeit zur Interaktion mit den Daten über die von Ihnen erstellten SPs besteht.

Verwenden Sie Ad-hoc-Abfragen:

  1. Für CRUD, wenn Sie den Datenzugriff nicht einschränken müssen (oder dies auf andere Weise tun).
  2. Für einfache Suchen.Das Erstellen von SPs für eine Reihe von Suchkriterien ist mühsam und schwierig zu pflegen.Wenn Sie eine einigermaßen schnelle Suchanfrage generieren können, verwenden Sie diese.

In den meisten meiner Anwendungen habe ich sowohl SPs als auch Ad-hoc-SQL verwendet, obwohl ich finde, dass ich SPs immer seltener verwende, da es sich letztendlich um Code wie C# handelt, der nur schwieriger zu versionieren, zu testen und zu warten ist.Ich würde die Verwendung von Ad-hoc-SQL empfehlen, es sei denn, Sie können einen bestimmten Grund finden, dies nicht zu tun.

Andere Tipps

Ich kann mit nichts anderem als SQL Server sprechen, aber das Leistungsargument ist es nicht Es ist dort weitgehend gültig, es sei denn, Sie verwenden Version 6.5 oder früher.SQL Server speichert Ad-hoc-Ausführungspläne seit etwa einem Jahrzehnt zwischen.

Gespeicherte Prozeduren stellen einen Softwarevertrag dar, der die gegen die Datenbank durchgeführten Aktionen kapselt.Der Code in den Prozeduren und sogar das Schema der Datenbank selbst können geändert werden, ohne dass sich dies auf den kompilierten, bereitgestellten Code auswirkt, sodass die Ein- und Ausgaben der Prozedur gleich bleiben.

Durch die Einbettung von Abfragen in Ihre Anwendung binden Sie sich eng an Ihr Datenmodell.

Aus dem gleichen Grund empfiehlt es sich auch nicht, einfach gespeicherte Prozeduren zu erstellen, bei denen es sich lediglich um CRUD-Abfragen für jede Tabelle in Ihrer Datenbank handelt, da es sich hierbei immer noch um eine enge Kopplung handelt.Die Verfahren sollten stattdessen umfangreiche, grobkörnige Vorgänge sein.

Aus Sicherheitsgründen empfiehlt es sich, db_datareader und db_datawriter aus Ihrer Anwendung auszuschließen und nur den Zugriff auf gespeicherte Prozeduren zuzulassen.

Ich denke, das ist ein grundlegender Konflikt zwischen Leuten, die die Datenbank pflegen müssen, und Leuten, die die Benutzeroberflächen entwickeln.

Als Datenperson würde ich nicht in Betracht ziehen, mit einer Datenbank zu arbeiten, auf die über Ad-hoc-Abfragen zugegriffen wird, da diese schwierig effektiv zu optimieren oder zu verwalten sind.Wie kann ich wissen, welche Auswirkungen eine Änderung am Schema haben wird?Darüber hinaus glaube ich nicht, dass Benutzern aus Sicherheitsgründen jemals direkter Zugriff auf die Datenbanktabellen gewährt werden sollte (und ich meine nicht nur SQL-Injection-Angriffe, sondern auch, weil es eine grundlegende interne Kontrolle ist, keine direkten Rechte zuzulassen und dies von allen Benutzern zu verlangen). Verwenden Sie nur die für die App entwickelten Prozesse.Dadurch soll möglichem Betrug vorgebeugt werden.Jedes Finanzsystem, das direkte Einfüge-, Aktualisierungs- oder Löschrechte für Tabellen zulässt, birgt ein großes Betrugsrisiko.Das ist eine schlechte Sache.).

Datenbanken sind nicht objektorientiert und Code, der aus objektorientierter Sicht gut erscheint, kann aus Datenbanksicht extrem schlecht sein.

Unsere Entwickler sagen uns, dass sie froh sind, dass unser gesamter Datenbankzugriff über Prozesse erfolgt, da es dadurch viel schneller geht, einen datenzentrierten Fehler zu beheben und den Prozess dann einfach in der Produktionsumgebung auszuführen, anstatt einen neuen Zweig des Codes zu erstellen und ihn neu zu kompilieren Neu laden in die Produktion.Wir verlangen, dass sich alle unsere Prozesse in Subversion befinden, sodass die Quellcodeverwaltung überhaupt kein Problem darstellt.Wenn es nicht in Subversion vorhanden ist, wird es regelmäßig vom DBA gelöscht, sodass es keinen Widerstand gegen die Verwendung der Quellcodeverwaltung gibt.

Gespeicherte Prozeduren sind auf jeden Fall der richtige Weg. Sie werden kompiliert, es liegt ein Ausführungsplan vor und Sie können die Rechteverwaltung für sie durchführen.

Ich verstehe dieses ganze Problem der Quellcodeverwaltung bei gespeicherten Prozeduren nicht.Sie können sie auf jeden Fall per Quellcode verwalten, wenn Sie nur ein wenig diszipliniert sind.

Beginnen Sie immer mit einer SQL-Datei, die die Quelle Ihrer gespeicherten Prozedur ist.Stellen Sie es in die Versionskontrolle, sobald Sie Ihren Code geschrieben haben.Wenn Sie Ihre gespeicherte Prozedur das nächste Mal bearbeiten möchten, beziehen Sie sie aus Ihrer Quellcodeverwaltung und nicht aus Ihrer Datenbank.Wenn Sie dies befolgen, verfügen Sie über eine ebenso gute Quellcodeverwaltung wie Ihr Code.

Ich möchte hier Tom Kyte von Oracle zitieren ... Hier ist seine Regel, wo man Code schreibt ... wenn auch etwas unabhängig, aber gut zu wissen, denke ich.

  1. Beginnen Sie mit gespeicherten Prozeduren in PL/SQL...
  2. Wenn Sie der Meinung sind, dass mit der gespeicherten Prozedur in PL/SQL etwas nicht möglich ist, verwenden Sie die gespeicherte Java-Prozedur.
  3. Wenn Sie der Meinung sind, dass mit der gespeicherten Java-Prozedur etwas nicht möglich ist, ziehen Sie Pro*c in Betracht.
  4. Wenn Sie der Meinung sind, dass Sie mit Pro*C nichts erreichen können, sollten Sie vielleicht noch einmal darüber nachdenken, was Sie tun müssen.

In unserer Anwendung gibt es eine Codeebene, die den Inhalt der Abfrage bereitstellt (und manchmal einen Aufruf einer gespeicherten Prozedur darstellt).Dies ermöglicht uns:

  • Sie können problemlos alle Abfragen unter Versionskontrolle haben
  • um alle erforderlichen Änderungen an jeder Abfrage für verschiedene Datenbankserver vorzunehmen
  • eliminiert die Wiederholung desselben Abfragecodes in unserem gesamten Code

Die Zugriffskontrolle wird in der mittleren Schicht und nicht in der Datenbank implementiert, sodass wir dort keine gespeicherten Prozeduren benötigen.Dies ist in gewisser Weise ein Mittelweg zwischen Ad-hoc-Abfragen und gespeicherten Prozessen.

Meine Antwort von einem anderen Post:Gespeicherte Prozeduren sind MEHR wartbar, weil:

  • Sie müssen Ihre C#-App nicht jedes Mal neu kompilieren, wenn Sie SQL ändern möchten
  • Am Ende verwenden Sie SQL-Code wieder.

Codewiederholung ist die am schlimmsten Was Sie tun können, wenn Sie versuchen, eine wartbare Anwendung zu erstellen!

Was passiert, wenn Sie einen Logikfehler finden, der an mehreren Stellen korrigiert werden muss?Es ist wahrscheinlicher, dass Sie vergessen, die letzte Stelle zu ändern, an der Sie Ihren Code kopiert und eingefügt haben.

Meiner Meinung nach sind die Leistungs- und Sicherheitsgewinne ein zusätzlicher Pluspunkt. Sie können weiterhin unsichere/ineffiziente gespeicherte SQL-Prozeduren schreiben.

Einfacher auf eine andere Datenbank zu portieren – keine Prozesse beim Portieren

Es ist nicht sehr schwierig, alle Ihre gespeicherten Prozeduren per Skript für die Erstellung in einer anderen Datenbank zu erstellen.Tatsächlich ist es so Einfacher als Ihre Tabellen zu exportieren, da Sie sich keine Sorgen um Primär-/Fremdschlüssel machen müssen.

Für beides gibt es überzeugende Argumente: Gespeicherte Prozeduren befinden sich alle in einem zentralen Repository, sind jedoch (potenziell) schwer zu migrieren und Ad-hoc-Abfragen sind einfacher zu debuggen als mit Ihrem Code, können aber auch schwieriger im Repository zu finden sein Code.

Das Argument, dass gespeicherte Prozeduren effizienter seien, ist nicht mehr stichhaltig.Link Text

Wenn Sie eine Google-Suche nach gespeicherter Prozedur oder dynamischer Abfrage durchführen, werden in beiden Fällen gute Argumente angezeigt und es ist wahrscheinlich das Beste für Sie, Ihre eigene Entscheidung zu treffen ...

Speicherprozeduren sollten so oft wie möglich verwendet werden, wenn Sie beim Schreiben von SQL in Code bereits in der Zukunft auf Probleme stoßen.Das Schreiben eines SPROC dauert ungefähr genauso lange wie das Schreiben im Code.

Stellen Sie sich eine Abfrage vor, die bei mittlerer Auslastung gut läuft, aber sobald sie in die Vollzeitproduktion geht, überlastet Ihre schlecht optimierte Abfrage das System und bringt es zum Crawlen.Bei den meisten SQL-Servern sind Sie nicht die einzige Anwendung/der einzige Dienst, der/die es verwendet.Ihre Bewerbung hat jetzt eine Menge verärgerter Menschen an Ihre Tür gebracht.

Wenn Sie Ihre Abfragen in SPROCs haben, überlassen Sie Ihrem freundlichen DBA auch die Verwaltung und Optimierung, ohne Ihre App neu zu kompilieren oder zu beschädigen.Denken Sie daran, dass Datenbankadministratoren Experten auf diesem Gebiet sind und wissen, was zu tun ist und was nicht.Es macht Sinn, ihr größeres Wissen zu nutzen!

BEARBEITEN:Jemand hat gesagt, dass Neukompilieren eine faule Ausrede ist!Ja, mal sehen, wie faul Sie sich fühlen, wenn Sie Ihre App neu kompilieren und auf Tausenden von Desktops bereitstellen müssen, und das alles nur, weil der DBA Ihnen mitgeteilt hat, dass Ihre Ad-hoc-Abfrage zu viel Serverzeit frisst!

Jemand hat gesagt, dass Neukompilieren eine faule Ausrede ist!Ja, mal sehen, wie faul Sie sich fühlen, wenn Sie Ihre App neu kompilieren und auf Tausenden von Desktops bereitstellen müssen, und das alles nur, weil der DBA Ihnen mitgeteilt hat, dass Ihre Ad-hoc-Abfrage zu viel Serverzeit frisst!

Ist es eine gute Systemarchitektur, wenn Sie 1000 Desktops direkt mit der Datenbank verbinden lassen?

Einige Dinge, über die Sie hier nachdenken sollten: Wer braucht überhaupt gespeicherte Prozeduren?

Natürlich ist es eine Frage Ihrer eigenen Bedürfnisse und Vorlieben, aber ein sehr wichtiger Aspekt, den Sie bei der Verwendung von Ad-hoc-Abfragen in einer öffentlich zugänglichen Umgebung berücksichtigen sollten, ist die Sicherheit.Parametrisieren Sie sie immer und achten Sie auf typische Schwachstellen wie z SQL-Injection-Angriffe.

Gespeicherte Prozeduren sind großartig, weil sie ohne Neukompilierung geändert werden können.Ich würde versuchen, sie so oft wie möglich zu verwenden.

Ich verwende Ad-hoc nur für Abfragen, die dynamisch basierend auf Benutzereingaben generiert werden.

Procs aus den von anderen genannten Gründen und außerdem ist es einfacher, einen Proc mit einem Profiler oder Teilen eines Procs abzustimmen.Auf diese Weise müssen Sie niemandem sagen, dass er seine App ausführen soll, um herauszufinden, was an den SQL-Server gesendet wird

Wenn Sie Ad-hoc-Abfragen verwenden, stellen Sie sicher, dass diese parametrisiert sind

Parametisiertes SQL oder SPROC ... spielt aus Leistungssicht keine Rolle ... Sie können beides abfragen.

Für mich besteht der letzte verbleibende Vorteil eines SPROC darin, dass ich eine Menge SQL-Rechteverwaltung eliminieren kann, indem ich nur meine Anmelderechte zum Ausführen von Sprocs erteile. Wenn Sie parametrisiertes SQL verwenden, hat die Anmeldung innerhalb Ihrer Verbindungszeichenfolge viel mehr Rechte (Schreiben ANY (z. B. eine Art Select-Anweisung für eine der Tabellen, auf die sie auch Zugriff haben).

Ich bevorzuge jedoch immer noch parametisiertes SQL ...

Ich habe kein überzeugendes Argument für die Verwendung von Ad-hoc-Abfragen gefunden.Vor allem diejenigen, die mit Ihrem C#/Java/PHP-Code verwechselt werden.

Das Argument der Sproc-Leistung ist strittig – die drei Top-RDBMs verwenden Abfrageplan-Caching und das schon seit einiger Zeit.Es wurde dokumentiert...Oder ist es noch 1995?

Allerdings ist die Einbettung von SQL in Ihre App auch ein schreckliches Design – die Codepflege scheint für viele ein fehlendes Konzept zu sein.

Wenn eine Anwendung mit einem ORM von Grund auf neu beginnen kann (Greenfield-Anwendungen gibt es nur sehr selten!), ist dies eine gute Wahl, da Ihr Klassenmodell Ihr DB-Modell steuert – und VIEL Zeit spart.

Wenn kein ORM-Framework verfügbar ist, haben wir einen hybriden Ansatz gewählt und eine SQL-Ressourcen-XML-Datei erstellt, um bei Bedarf nach SQL-Zeichenfolgen zu suchen (sie werden dann vom Ressourcen-Framework zwischengespeichert).Wenn die SQL geringfügige Manipulationen erfordert, erfolgt dies im Code. Wenn größere SQL-String-Manipulationen erforderlich sind, überdenken wir den Ansatz.

Dieser hybride Ansatz ermöglicht eine einfache Verwaltung durch die Entwickler (vielleicht sind wir die Minderheit, da mein Team klug genug ist, einen Abfrageplan zu lesen) und die Bereitstellung erfolgt durch einen einfachen Checkout von SVN.Außerdem wird der Wechsel von RDBMs einfacher – einfach die SQL-Ressourcendatei austauschen (natürlich nicht so einfach wie ein ORM-Tool, aber die Verbindung zu Legacy-Systemen oder nicht unterstützten Datenbanken funktioniert)

Hängt davon ab, was Ihr Ziel ist.Wenn Sie eine Liste von Elementen abrufen möchten und dies beispielsweise einmal während der gesamten Ausführung Ihrer Anwendung geschieht, lohnt sich der Aufwand für die Verwendung einer gespeicherten Prozedur wahrscheinlich nicht.Andererseits ist eine Abfrage, die wiederholt ausgeführt wird und deren Ausführung (relativ) lange dauert, ein hervorragender Kandidat für die Datenbankspeicherung, da die Leistung besser ist.

Wenn Ihre Anwendung fast vollständig in der Datenbank gespeichert ist, sind gespeicherte Prozeduren ein Kinderspiel.Wenn Sie eine Desktop-Anwendung schreiben, für die die Datenbank nur am Rande wichtig ist, sind Ad-hoc-Abfragen möglicherweise die bessere Option Bewahrt Ihren gesamten Code an einem Ort auf.

@Terrapin:Ich denke, Ihre Behauptung, dass die Tatsache, dass Sie Ihre App nicht neu kompilieren müssen, um Änderungen vorzunehmen, gespeicherte Prozeduren zu einer besseren Option macht, ist ein Fehlschlag.Es kann Gründe dafür geben, gespeicherte Prozeduren Ad-hoc-Abfragen vorzuziehen, aber da nichts anderes Zwingendes vorliegt, scheint das Kompilierungsproblem eher Faulheit als ein wirklicher Grund zu sein.

Ich habe die Erfahrung gemacht, dass 90 % der Abfragen und/oder gespeicherten Prozeduren überhaupt nicht geschrieben werden sollten (zumindest nicht von Hand).

Der Datenzugriff sollte irgendwie automatisch generiert werden.Sie können entscheiden, ob Sie Prozeduren statisch zur Kompilierungszeit oder dynamisch zur Laufzeit generieren möchten. Wenn Sie jedoch eine Spalte zur Tabelle (Eigenschaft zum Objekt) hinzufügen möchten, sollten Sie nur eine Datei ändern.

Ich bevorzuge es, alle Daten aufzubewahren Zugang Logik im Programmcode, bei der die Datenzugriffsschicht direkte SQL-Abfragen ausführt.Andererseits Daten Management Logik, die ich in Form von Triggern, gespeicherten Prozeduren, benutzerdefinierten Funktionen und so weiter in die Datenbank eingefügt habe.Ein Beispiel für etwas, das meiner Meinung nach einer Datenbankoptimierung würdig ist, ist die Datengenerierung – gehen wir davon aus, dass unser Kunde einen Vornamen und einen Nachnamen hat.Nun benötigt die Benutzeroberfläche einen DisplayName, der aus einer nichttrivialen Logik abgeleitet ist.Für diese Generation erstelle ich eine gespeicherte Prozedur, die dann von einem Trigger ausgeführt wird, wenn die Zeile (oder andere Quelldaten) aktualisiert wird.

Es scheint ein weit verbreitetes Missverständnis zu geben, dass die Datenzugriffsschicht die Datenbank IST und alles, was mit Daten und Datenzugriff zu tun hat, dort „einfach so“ abgelegt wird.Das ist einfach falsch, aber ich sehe viele Designs, die von dieser Idee abgeleitet sind.Möglicherweise handelt es sich hierbei jedoch um ein lokales Phänomen.

Möglicherweise bin ich von der Idee mit SPs abgeschreckt, nachdem ich so viele schlecht gestaltete gesehen habe.Beispielsweise verwendete ein Projekt, an dem ich beteiligt war, einen Satz gespeicherter CRUD-Prozeduren für jede Tabelle und jede mögliche Abfrage, auf die sie stießen.Dabei fügten sie einfach eine weitere völlig sinnlose Ebene hinzu.Es ist schmerzhaft, überhaupt über solche Dinge nachzudenken.

Heutzutage verwende ich kaum noch gespeicherte Prozeduren.Ich verwende sie nur für komplizierte SQL-Abfragen, die nicht einfach im Code durchgeführt werden können.

Einer der Hauptgründe ist, dass gespeicherte Prozeduren mit OR-Mappern nicht so gut funktionieren.

Heutzutage braucht man meiner Meinung nach einen sehr guten Grund, eine Geschäftsanwendung/ein Informationssystem zu schreiben, das keinen OR-Mapper verwendet.

Gespeicherte Prozeduren funktionieren als Codeblock, sodass sie anstelle einer Ad-hoc-Abfrage schnell funktionieren.Eine andere Sache ist eine gespeicherte Prozedur Geben Sie die Option "Recompile", die Sie im besten Teil von SQL nur für gespeicherte Prozeduren verwenden.

Einige führen dazu, dass Abfrage und gespeicherte Prozedur unterschiedlich sind, das ist meine persönliche Erfahrung.Verwenden Sie die Cast- und Covert-Funktion, um dies zu überprüfen.

Für große Projekte muss eine gespeicherte Prozedur verwendet werden, um die Leistung zu verbessern.

Ich hatte 420 Prozeduren in meinem Projekt und es funktioniert für mich einwandfrei.Ich arbeite seit 3 ​​Jahren an diesem Projekt.

Verwenden Sie daher für jede Transaktion nur Verfahren.

Ist es eine gute Systemarchitektur, wenn Sie 1000 Desktops direkt an die Datenbank anschließen lassen?

Nein, das ist es offensichtlich nicht, es ist vielleicht ein schlechtes Beispiel, aber ich denke, der Punkt, den ich ansprechen wollte, ist klar: Ihr DBA kümmert sich um Ihre Datenbank-Infrastruktur, da dort sein Fachwissen liegt, und wenn er SQL in Code stopft, verschließt er ihm und seinem Fachwissen die Tür.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top