Ich arbeite bei einem Projekt in einem der drei weltweit führenden IT-Beratungsunternehmen und wurde von einem DBA darauf hingewiesen, dass die in einem Best Practice-Verfahren gespeicherten Statusprozeduren kein "Best Practice" sind. Dies steht im Widerspruch zu allem, was ich gelernt habe.
Gespeicherte Prozeduren ermöglichen die Wiederverwendung von Code und die Kapselung (zwei Säulen der Softwareentwicklung), die Sicherheit (Sie können Berechtigungen für einen einzelnen gespeicherten Prozess erteilen / entziehen), schützen Sie vor SQL-Injection-Angriffen und beschleunigen die Ausführung (obwohl dies vom DBA angegeben wurde) Beginnend mit SQL Server 2008 werden sogar reguläre SQL-Abfragen kompiliert, wenn sie genügend oft ausgeführt werden.
Wir entwickeln eine komplexe App unter Verwendung der Agile-Softwareentwicklungsmethode. Kann sich jemand gute Gründe vorstellen, warum er gespeicherte Procs nicht verwenden möchte? Ich vermute, dass die Datenbankadministratoren diese gespeicherten Prozesse nicht beibehalten wollten, aber es scheint zu viele Negative zu geben, um eine solche Entwurfsentscheidung zu rechtfertigen.
quelle
Antworten:
Nach meiner Erfahrung bei der Arbeit an sehr großen Projekten muss klar sein, wo Geschäftslogik lebt. Wenn Sie eine Umgebung zulassen, in der einzelne Entwickler Geschäftslogik nach eigenem Ermessen in die Geschäftsobjektschicht oder in eine gespeicherte Prozedur einfügen können, ist eine große Anwendung SEHR schwer zu verstehen und zu warten.
Gespeicherte Prozeduren sind ideal, um bestimmte DB-Vorgänge zu beschleunigen. Meine architektonische Entscheidung besteht darin, die gesamte Logik in der Geschäftsschicht der Anwendung zu belassen und gespeicherte Prozeduren gezielt einzusetzen, um die Leistung dort zu verbessern, wo das Benchmarking dies rechtfertigt.
quelle
Einige Beobachtungen
Nur wenn Sie sie in dem Kontext verwenden, in dem sie verwendet werden sollen. Dieselbe Behauptung kann über Funktionen (in strukturierter Programmierung) oder Methoden (in objektorientierter Programmierung) aufgestellt werden, und dennoch sehen wir 1K-Funktionen und mega-ass-Objekte.
Artefakte bieten Ihnen diese Vorteile nicht. Die richtige Verwendung dieser Artefakte ist der Grund für diese Vorteile.
Ja. Dies ist ein guter Punkt und einer der Hauptgründe, warum ich gespeicherte Prozeduren mag. Sie bieten eine feinere Zugriffskontrolle als dies normalerweise nur mit Ansichten und Benutzerkonten möglich ist.
Dies ist für SPs nicht spezifisch, da Sie mit parametrisierten SQL-Anweisungen und Eingabebereinigung das gleiche Schutzniveau erreichen können. Ich würde jedoch zusätzlich zu diesen SPs aus Gründen der "Sicherheit in der Tiefe" verwenden .
Dies ist in hohem Maße herstellerspezifisch für Datenbanken, aber im Allgemeinen hat Ihr DBA Recht. SQL-Anweisungen (entweder statisch oder parametrisiert) werden kompiliert. SPs helfen, wenn Sie Daten aggregieren und berechnen möchten / müssen, die Sie nicht mit einfachen SQL-Anweisungen ausführen können, die jedoch eng in SQL integriert sind und für die kein Roundtrip zum App-Server erforderlich ist.
Ein gutes Beispiel ist das Abfragen von Daten in einen temporären Cursor (oder Cursor), von dem aus ein anderes SQL ausgeführt werden soll. Sie können dies programmgesteuert auf dem App-Server tun, oder Sie können die Mehrfach-Roundtrips speichern, indem Sie dies in der Datenbank tun.
Dies sollte jedoch nicht die Norm sein. Wenn Sie viele dieser Fälle haben, ist dies ein Zeichen für einen schlechten Datenbankentwurf (oder Sie beziehen Daten aus nicht so kompatiblen Datenbankschemata abteilungsübergreifend).
Agilität hat mit Software-Engineering-Prozessen und Anforderungsmanagement zu tun, nicht mit Technologien.
Falsche Frage
Die Frage ist falsch und entspricht der Frage "Gibt es gute Gründe, GOTO nicht zu verwenden?" Ich stehe mehr auf der Seite von Niklaus Wirth als auf der Seite von Dijkstra. Ich kann verstehen, woher Dijkstras Gefühl kam, aber ich glaube nicht, dass es in allen Fällen zu 100% zutreffend ist. Gleiches gilt für Store Procs und jegliche Technologie.
Ein Werkzeug ist gut, wenn es für den vorgesehenen Zweck gut verwendet wird und wenn es das beste Werkzeug für die jeweilige Aufgabe ist. Andernfalls bedeutet dies nicht, dass das Werkzeug falsch ist, der Benutzer jedoch nicht weiß, was er tut.
Die richtige Frage lautet: "Welche Art von Nutzungsmustern für gespeicherte Prozeduren sollte vermieden werden?" Oder "unter welchen Bedingungen sollte ich gespeicherte Prozeduren verwenden (oder nicht)" . Wenn Sie nach Gründen suchen , eine Technologie nicht zu verwenden, geben Sie dem Werkzeug einfach die Schuld, anstatt die technische Verantwortung genau dort zu platzieren, wo sie hingehört - beim Ingenieur.
Mit anderen Worten, es ist eine Ausrede oder eine Erklärung der Unwissenheit.
Sie projizieren dann die Ergebnisse ihrer schlechten technischen Entscheidungen auf die Werkzeuge, die sie schlecht eingesetzt haben.
Was ist in Ihrem Fall zu tun?
Meine Erfahrung ist, wenn ich in Rom bin, mache ich es wie die Römer .
Kämpfe nicht dagegen an. Wenn die Leute in Ihrem Unternehmen Geschäftsprozesse als schlechte Praxis bezeichnen möchten, lassen Sie sie. Beachten Sie jedoch, dass dies eine rote Fahne in ihren Entwicklungspraktiken sein kann.
Eine typische Kennzeichnung von Dingen als schlechte Praxis erfolgt normalerweise in Organisationen mit Tonnen von inkompetenten Programmierern. Indem die Organisation bestimmte Dinge auflistet, versucht sie, den Schaden zu begrenzen, der intern durch ihre eigene Inkompetenz verursacht wird. Ich scheiße dich nicht.
Verallgemeinerungen sind die Mutter aller Fehler. Zu sagen, dass gespeicherte Prozesse (oder jede Art von Technologie) eine schlechte Praxis sind, ist eine Verallgemeinerung. Verallgemeinerungen sind Ausreden für Inkompetente. Ingenieure arbeiten nicht mit offensichtlichen Verallgemeinerungen. Sie analysieren von Fall zu Fall, analysieren Kompromisse und treffen technische Entscheidungen und Lösungen gemäß den vorliegenden Fakten, in deren Kontext sie ein Problem lösen sollen.
Gute Ingenieure bezeichnen Dinge nicht so verallgemeinernd als schlechte Praxis. Sie sehen sich das Problem an, wählen das geeignete Werkzeug aus und machen Kompromisse. Mit anderen Worten, sie machen Engineering.
Meine Meinung, wie man sie nicht benutzt
Setzen Sie komplexe Logik nicht über das Sammeln von Daten (und möglicherweise einige Transformationen) hinaus ein. Es ist in Ordnung, Datenmassagelogik in diese zu integrieren oder das Ergebnis mehrerer Abfragen mit diesen zu aggregieren. Aber das war es schon. Alles darüber hinaus würde sich als Geschäftslogik qualifizieren, die sich woanders befinden sollte.
Verwenden Sie sie nicht als einzigen Schutzmechanismus gegen SQL-Injection. Sie lassen sie dort, falls etwas Schlimmes für sie zutrifft , aber es sollte eine Menge defensiver Logik vor ihnen stehen - clientseitige Validierung / Bereinigung, serverseitige Validierung / Bereinigung, möglicherweise Umwandlung in Typen, die für Sie sinnvoll sind Domänenmodell und schließlich an parametrisierte Anweisungen übergeben werden (dies können parametrisierte SQL-Anweisungen oder parametrisierte gespeicherte Prozesse sein).
Machen Sie Datenbanken nicht zum einzigen Ort, an dem sich Ihre Geschäftsprozesse befinden. Ihre Geschäftsprozesse sollten genauso behandelt werden, wie Sie Ihren C # - oder Java-Quellcode behandeln. Das heißt, die Quellcodeverwaltung steuert die Textdefinition Ihrer Geschäftsprozesse. Die Leute schimpfen darüber, dass Geschäftsprozesse nicht von der Quelle kontrolliert werden können - Bullcrap, sie wissen einfach nicht, wovon zum Teufel sie reden.
Meine Meinung, wie / wo man sie benutzt
Ihre Anwendung erfordert Daten, die aus mehreren Abfragen oder Ansichten transponiert oder aggregiert werden müssen. Sie können das von der Anwendung in die Datenbank auslagern. Hier haben Sie eine Performance - Analyse zu tun , da a) Datenbank - Engines effizienter ist , dass App - Server in diese Dinge zu tun, aber b) App - Server sind (manchmal) leichter horizontal zu skalieren.
Feinkörnige Zugangskontrolle. Sie möchten nicht, dass ein Idiot kartesische Joins in Ihrer Datenbank ausführt, aber Sie können auch nicht einfach Leuten verbieten, beliebige SQL-Anweisungen einfach so auszuführen. Eine typische Lösung besteht darin, beliebige SQL-Anweisungen in Entwicklungs- und UAT-Umgebungen zuzulassen und sie in System- und Produktionsumgebungen zu verbieten. Jede Aussage, die es zu systest oder zur Produktion schaffen muss, geht in eine Speicherprozedur, die sowohl von Entwicklern als auch von dbas mit Code überprüft wird.
Jeder gültige Bedarf, eine SQL-Anweisung auszuführen, die sich nicht in einem Geschäftsprozess befindet, durchläuft einen anderen Benutzernamen / Konto und Verbindungspool (wobei die Verwendung stark überwacht wird und davon abgeraten wird.)
Ob Sie dies auf der Datenbank als Store Proc oder auf Ihrem App-Server ausführen, hängt von der Abwägungsanalyse ab, die Sie als Ingenieur durchführen müssen. Beide Optionen müssen analysiert und mit einer Art Analyse begründet werden. Auf die eine oder andere Weise die andere Alternative einfach als "schlechte Praxis" zu beschuldigen, das ist nur eine lahme Auseinandersetzung mit der Technik.
Ob dies nun zu einer dauerhaften Lösung wird oder nicht, das ist spezifisch für die in diesem bestimmten Moment beobachteten Einschränkungen.
Ich hoffe es hilft.
quelle
Das Grundprinzip ist, dass die Verwendung einer gespeicherten Prozedur die Portabilität einschränkt und Sie an eine bestimmte Datenbank bindet. Hinzugefügte Wartungskosten werden ebenfalls als Grund angeführt. Ich wollte auch diesen Punkt kommentieren, den Sie gemacht haben:
Tatsächlich schützt Sie die parametrisierte Abfrage, die Sie bei der SQL-Abfrage mit einfachem Text problemlos ausführen können.
quelle
+ "blablabla"
da Sie einfaches SQL zulassen müssen. Hier endet die Kontrolle.Einige der Gründe, denen ich zustimme, dass gespeicherte Prozesse nicht die beste Vorgehensweise sind.
quelle
Ja, aber auf Kosten anderer agiler Designziele. Zum einen sind sie schwieriger zu warten. Wenn das Projekt, an dem ich arbeite, ein Indiz ist, werden Sie wahrscheinlich mehrere inkompatible SPs haben, die im Wesentlichen die gleiche Arbeit leisten, ohne dass dies von Vorteil ist.
Nein tun sie nicht. Ich kann nicht einmal ahnen, woher diese Idee gekommen sein könnte, wie ich oft gehört habe, und sie ist einfach nicht wahr. Es kann bestimmte Arten von SQL-Injection-Angriffen abschwächen, aber wenn Sie nicht in erster Linie parametrisierte Abfragen verwenden, spielt das keine Rolle. Ich kann immer noch '; DROP TABLE Accounts; -
Sie werden normalerweise auch kompiliert, wenn Sie vorbereitete, parametrisierte Anweisungen verwenden (zumindest mit mehreren der von mir verwendeten DBs). Zu dem Zeitpunkt, an dem Ihre Anwendung mit der Ausführung der Abfrage beginnt (oder insbesondere, wenn Sie dieselbe vorbereitete Abfrage mehrmals ausführen), ist jeder Leistungsvorteil, den Sie für Ihren SP halten, völlig hinfällig.
Der einzige Grund für die Verwendung einer gespeicherten Prozedur (IMHO) besteht darin, dass Sie eine komplexe, mehrstufige Abfrage erstellen müssen, die aus mehreren sortierten Quellen stammt. SPs sollten keine Entscheidungslogik auf niedriger Ebene enthalten, und sie sollten niemals einfach eine ansonsten einfache Abfrage kapseln. Es gibt keine Vorteile und nur viele Nachteile.
Hören Sie auf Ihren DBA. Er weiß, was los ist.
quelle
Dies war die offizielle Linie, als ich vor ein paar Jahren für einen der Big Five arbeitete. Das Grundprinzip war, dass SPs, da sie an bestimmte Implementierungen gebunden sind (PL / SQL vs. T / SQL vs. ...), die Auswahl an Technologien unnötig einschränken.
Nachdem ich die Migration eines großen Systems von T / SQL zu PL / SQL erlebt habe, kann ich das Argument verstehen. Ich denke, es ist ein bisschen wie ein Trottel - wie viele Orte bewegen sich wirklich aus einer Laune heraus von einer Datenbank in eine andere?
quelle
Alle drei Unternehmen, für die ich arbeite, haben gespeicherte Prozeduren für ihre Anwendungslogik mit SQL Server verwendet. Ich habe die Dinge nicht wirklich anders gesehen. Aber für mich sind sie ein großes Durcheinander. In der Regel gibt es keine sehr guten Möglichkeiten zur Fehlerbehandlung oder Wiederverwendung von Code mit gespeicherten Prozeduren.
Angenommen, Sie haben eine gespeicherte Prozedur, die ein Dataset zurückgibt, das Sie verwenden möchten. Wie können Sie es in zukünftigen gespeicherten Prozeduren verwenden? Die Mechanismen auf SQL Server dafür sind nicht sehr gut. EXEC INTO ... funktioniert nur auf einer oder zwei Verschachtelungsebenen (ich vergesse jetzt). Oder Sie müssen eine Arbeitstabelle vordefinieren und sie verschlüsseln lassen. Oder Sie müssen eine temporäre Tabelle vorab erstellen und von der Prozedur füllen lassen. Aber was ist, wenn zwei Personen eine temporäre Tabelle in zwei verschiedenen Prozeduren, die sie nie zur gleichen Zeit verwenden wollten, als dasselbe bezeichnen? In jeder normalen Programmiersprache können Sie einfach ein Array von einer Funktion oder einem Punkt auf ein zwischen ihnen geteiltes Objekt / eine globale Struktur zurückgeben (außer in funktionalen Sprachen, in denen Sie die Datenstruktur zurückgeben würden, anstatt nur eine globale Struktur zu ändern ... )
Wie wäre es mit der Wiederverwendung von Code? Wenn Sie anfangen, allgemeine Ausdrücke in UDFs (oder noch schlimmer in Unterabfragen) einzufügen, verlangsamen Sie den Code. Sie können keine gespeicherte Prozedur aufrufen, um eine Berechnung für eine Spalte durchzuführen (es sei denn, Sie verwenden einen Cursor, übergeben die Spaltenwerte nacheinander und aktualisieren dann irgendwie Ihre Tabelle / Ihr Dataset). Um also die bestmögliche Leistung zu erzielen, müssen Sie allgemeine Ausdrücke ausschneiden / einfügen. Dies ist ein Alptraum für die Wartung. Mit einer Programmiersprache können Sie eine Funktion erstellen, mit der Sie das allgemeine SQL generieren und es dann beim Erstellen von überall aufrufen können die SQL-Zeichenfolge. Wenn Sie dann die Formel anpassen müssen, können Sie die Änderung an einer einzigen Stelle vornehmen ...
Wie wäre es mit Fehlerbehandlung? SQL Server hat viele Fehler, die die Ausführung der gespeicherten Prozedur sofort stoppen, und einige, die sogar eine Trennung erzwingen. Seit 2005 gibt es try / catch, aber es gibt immer noch eine Reihe von Fehlern, die nicht abgefangen werden können. Dasselbe passiert auch mit der Code-Vervielfältigung im Fehlerbehandlungscode, und Sie können Ausnahmen nicht so einfach weitergeben oder auf höhere Ebenen bringen wie die meisten Programmiersprachen.
Auch nur Geschwindigkeit. Viele Operationen an Datensätzen sind nicht SET-orientiert. Wenn Sie versuchen, zeilenorientierte Dinge zu tun, verwenden Sie entweder einen Cursor oder einen "Cursor" (wenn Entwickler häufig jede Zeile einzeln abfragen und den Inhalt wie einen Cursor in @ -Variablen speichern). ..Auch wenn dies oft langsamer ist als ein FORWARD_ONLY-Cursor). Mit SQL Server 2000 hatte ich etwas, das 1 Stunde lief, bevor ich es tötete. Ich habe diesen Code in Perl umgeschrieben und er war in 20 Minuten fertig. Wenn eine Skriptsprache, die 20- bis 80-mal langsamer als C ist, die Leistung von SQL beeinträchtigt, haben Sie definitiv keine Möglichkeit, zeilenorientierte Operationen in SQL zu schreiben.
Jetzt verfügt SQL Server über eine CLR-Integration, und viele dieser Probleme werden behoben, wenn Sie gespeicherte CLR-Prozeduren verwenden. Viele Datenbankadministratoren wissen jedoch aus Sicherheitsgründen nicht, wie sie .NET-Programme schreiben oder die CLR deaktivieren sollen, und bleiben bei Transact SQL .
Auch im Allgemeinen ist die Datenbank am schwierigsten zu skalieren. Wenn sich Ihre gesamte Geschäftslogik in der Datenbank befindet, treten Probleme auf, wenn die Datenbank zu langsam wird. Wenn Sie eine Business-Schicht haben, können Sie einfach mehr Caching und mehr Business-Server hinzufügen, um die Leistung zu steigern. Traditionell ist ein anderer Server zum Installieren von Windows / Linux und Ausführen von .NET / Java viel billiger als der Kauf eines anderen Datenbankservers und die Lizenzierung von mehr SQL Server. SQL Server bietet jetzt mehr Clusterunterstützung, ursprünglich gab es keine. Wenn Sie also viel Geld haben, können Sie Clustering hinzufügen oder sogar einen Protokollversand durchführen, um mehrere schreibgeschützte Kopien zu erstellen. Aber insgesamt wird dies viel mehr kosten als nur einen Schreibzugriff hinter den Cache oder so.
Schauen Sie sich auch die Transact-SQL-Funktionen an. String-Manipulation? Ich nehme jeden Tag an den Klassen Java String Class / Tokenizer / Scanner / Regex teil. Hash-Tabellen / Verknüpfte Listen / usw. Ich nehme die Java Collection-Frameworks usw. und das Gleiche für .NET. Sowohl C # als auch Java sind weitaus weiterentwickelte Sprachen als Transact SQL. .
Darüber hinaus sind gespeicherte Prozeduren effizienter, wenn Sie mit einem großen Dataset arbeiten und mehrere Abfragen / Kriterien anwenden, um es zu verkleinern, bevor Sie es an die Business-Schicht zurückgeben. Wenn Sie eine Menge großer Datenmengen an die Clientanwendung senden und die Daten auf dem Client auflösen müssen, ist dies weitaus ineffizienter als die gesamte Arbeit auf dem Server.
Auch gespeicherte Prozeduren sind gut für die Sicherheit. Sie können den gesamten Zugriff auf die zugrunde liegenden Tabellen unterbrechen und den Zugriff nur über die gespeicherten Prozeduren zulassen. Mit einigen modernen Techniken wie XML können Sie gespeicherte Prozeduren haben, die Stapelaktualisierungen durchführen. Alle Zugriffe werden dann über die gespeicherten Prozeduren gesteuert, so lange sie sicher / korrekt sind und die Daten eine höhere Integrität aufweisen können.
Das SQL-Injection-Argument trifft nicht mehr wirklich zu, da wir programmiersprachliche Abfragen parametrisiert haben. Auch wirklich noch vor parametrisierten Abfragen hat ein wenig Ersetzen ("'", "'") die meiste Zeit auch funktioniert (obwohl es immer noch Tricks gibt, um über das Ende des Strings hinauszugehen, um das zu bekommen, was Sie wollen).
Insgesamt denke ich, dass SQL und Transact SQL großartige Sprachen zum Abfragen / Aktualisieren von Daten sind. Aber für das Codieren jeder Art von Logik, das Manipulieren von Strings (oder das Manipulieren von Dateien ... Sie wären überrascht, was Sie mit xp_cmdshell machen können ...) bitte nein. Ich hoffe, einen zukünftigen Ort zu finden, der meistens keine gespeicherten Prozeduren verwendet. Aus Sicht der Code-Wartbarkeit sind sie ein Albtraum. Was passiert auch, wenn Sie die Plattform wechseln möchten (obwohl Sie wirklich für Oracle / DB2 / Sybase / SQL Server / usw. bezahlt haben), können Sie genauso gut alles aus ihnen herausholen, indem Sie jede proprietäre Erweiterung verwenden, die Ihnen hilft. ..).
Auch überraschend oft ist die Geschäftslogik nicht die gleiche. In der idealen Welt würden Sie die gesamte Logik in gespeicherte Prozeduren einfügen und diese zwischen Anwendungen teilen. Die Logik unterscheidet sich jedoch häufig je nach Anwendung, und Ihre gespeicherten Prozeduren werden zu übermäßig komplexen Monolithen, von denen die Menschen Angst haben, sie zu ändern, und deren Auswirkungen sie nicht verstehen. Während mit einer guten objektorientierten Sprache eine Datenzugriffsebene codiert werden kann, die über einige Standardschnittstellen / -hooks verfügt, die jede Anwendung an ihre eigenen Anforderungen anpassen kann.
quelle
Wie versionieren Sie gespeicherte Prozeduren auf dem Server?
Wenn Sie gespeicherte Prozeduren aus der Versionskontrolle auf dem Server erneut bereitstellen, wird der gespeicherte Ausführungsplan ausgeblasen.
Gespeicherte Prozeduren sollten nicht direkt auf dem Server geändert werden können. Woher wissen Sie sonst, was gerade wirklich läuft? Ist dies nicht der Fall, benötigt das Bereitstellungstool Zugriff, um gespeicherte Prozeduren in die Datenbank schreiben zu können. Sie müssten bei jedem Build bereitgestellt werden (Ausführungsplan muss möglicherweise anders sein)
Während gespeicherte Prozeduren nicht portierbar sind, ist SQL im Allgemeinen auch nicht portierbar (jemals gesehene Oracle-Datumsverarbeitung - uggghhh).
Wenn Sie also Portabilität wünschen, erstellen Sie eine interne Datenzugriffs-API. Sie können dies wie Funktionsaufrufe aufrufen, und intern können Sie mit parametrisierten Abfragen beliebigen Jargon einbauen und es kann versionsgesteuert werden.
quelle
Möglicherweise müssen Sie mehr raus. [grinst] Im Ernst, gespeicherte Procs sind seit mindestens 10 Jahren rückläufig. Seitdem n-tier den Client-Server abgelöst hat. Der Rückgang wurde nur durch die Einführung von OO-Sprachen wie Java, C #, Python usw. beschleunigt.
Das heißt nicht, dass gespeicherte Procs noch keine Befürworter und Befürworter haben - aber dies ist eine langwierige Diskussion und Debatte. Es ist nicht neu und wird wahrscheinlich noch einige Zeit dauern. IMO, die Gegner der gespeicherten Procs gewinnen klar.
Sehr richtig. Dies gilt jedoch auch für eine anständig strukturierte OO-Ebene.
Während Sie das tun können, tun es nur wenige aufgrund der schwerwiegenden Einschränkungen. Die Sicherheit auf DB-Ebene ist nicht granular genug, um kontextsensitive Entscheidungen zu treffen. Aufgrund des Leistungsaufwands und des Verwaltungsaufwands ist es ungewöhnlich, dass auch Verbindungen pro Benutzer bestehen. Daher benötigen Sie in Ihrem App-Code immer noch eine gewisse Berechtigungsstufe. Sie können rollenbasierte Anmeldungen verwenden, müssen diese jedoch für neue Rollen erstellen, die ausgeführte Rolle verwalten, die Verbindungen wechseln, um auf "Systemebene" wie bei der Protokollierung zu arbeiten usw. Und letztendlich, wenn Ihre App gehört - ebenso wie Ihre Verbindung zur DB.
Nicht mehr als parametrisierte Abfragen. Welche Sie brauchen sowieso tun werden.
Ich denke, das begann in MSSQL 7 oder 2000. Es gab eine Menge Debatten, Messungen und Fehlinformationen über gespeicherte Prozesse im Vergleich zur Inline-SQL-Leistung - ich fasse alles unter YAGNI zusammen. Und wenn Sie es brauchen, testen Sie.
Ich kann mir nicht viele Gründe vorstellen, die Sie sich wünschen würden . Java / C # / jede dritte GL-Sprache ist in Bezug auf Kapselung, Wiederverwendung und Flexibilität usw. weitaus leistungsfähiger als T-SQL. Die meisten davon sind bei einem halbwegs anständigen ORM kostenlos.
Angesichts des Ratschlags, "nach Bedarf zu verteilen, aber nicht mehr" - denke ich, dass die Beweislast heutzutage bei SP-Befürwortern liegt. Ein häufiger Grund für das Speichern von Prozessen ist, dass T-SQL einfacher als OO ist und der Shop bessere T-SQL-Entwickler als OO hat. Oder dass der DBA auf der Datenbankebene stoppt und gespeicherte Prozesse die Schnittstelle zwischen dev und DBA sind. Oder Sie versenden ein halbkundenspezifisches Produkt und die gespeicherten Prozesse können vom Benutzer angepasst werden. In Abwesenheit solcher Überlegungen denke ich, dass der Standard für jedes Agile SW-Projekt heutzutage ORM sein wird.
quelle
In Anbetracht all dieser Fälle möchte ich noch einen hinzufügen. Die Wahl von SP kann auch von der Wahl der Leute abhängen.
Ich persönlich bin frustriert, wenn Leute sehr komplexe Logik in SP einbauen, und ich glaube, dass es sehr komplex ist, solche SP zu warten und zu debuggen. Sogar in vielen Fällen hat der Entwickler selbst Probleme, wenn das Debuggen im Code dahinter (sprich Sprachteil) viel einfacher ist als in SP.
SP sollte nur für einfache Operationen verwendet werden. Nun, das ist meine Wahl.
quelle
Ich möchte sowohl einige Pro- als auch Probleme mit gespeicherten Prozessen behandeln. Wir verwenden sie ausgiebig mit LedgerSMB , und unsere Regel lautet mit einigen sehr spezifischen Erweiterungen: "Wenn es sich um eine Abfrage handelt, machen Sie sie zu einem gespeicherten Prozess."
Unser Grund dafür war, die Wiederverwendung von Abfragen in verschiedenen Sprachen zu vereinfachen. Es gibt keinen besseren Weg, dies ehrlich zu tun.
Am Ende steht immer die Frage nach den Details. Gut eingesetzte gespeicherte Prozeduren erleichtern die Arbeit erheblich, und schlecht eingesetzte Prozeduren erschweren die Arbeit erheblich.
Also weiter zur Gegenseite.
Wie traditionell verwendet, sind gespeicherte Prozeduren spröde. Alleine verwendet, schaffen sie die Möglichkeit, Ihrem Code an Stellen Fehler hinzuzufügen, von denen Sie nicht erwartet haben, dass sich die Aufrufsyntax geändert hat. Allein genommen ist dies ein kleines Problem. Es gibt viel zu viel Zusammenhalt zwischen den Schichten und dies verursacht Probleme.
Ja, es ist möglich, eine Intra-Sproc-SQL-Injektion durchzuführen, wenn eine dynamische SQL durchgeführt wird. Es ist eine schlechte Sache, in diesem Bereich zu zuversichtlich zu sein, und daher muss man über umfangreiche Sicherheitserfahrung in diesem Bereich verfügen.
Änderungen an den Schnittstellen sind mit gespeicherten Prozeduren aus dem obigen Grund Nr. 1 etwas problematisch, aber dies kann ein sehr großer Albtraum werden, wenn eine große Anzahl von Client-Apps beteiligt ist.
Die oben genannten sind ziemlich schwer zu leugnen. Sie passieren. Jeder, Pro-SP und Anti-SP, hat wahrscheinlich Horrorgeschichten über diese gehabt. Die Probleme sind nicht unlösbar, aber wenn Sie sie nicht beachten, können Sie sie nicht lösen (in LedgerSMB verwenden wir einen Service Locator, um SP-Aufrufe zur Laufzeit dynamisch zu erstellen und die oben genannten Probleme vollständig zu vermeiden. Während wir PostgreSQL sind nur könnte etwas ähnliches für andere db's gemacht werden).
Auf zum Positiven. Angenommen, Sie können die oben genannten Probleme lösen, erhalten Sie:
Die Möglichkeit einer besseren Übersichtlichkeit bei Set-Vorgängen. Dies gilt insbesondere dann, wenn Ihre Anfrage sehr umfangreich oder sehr flexibel ist. Dies führt auch zu einer verbesserten Testbarkeit.
Wenn ich bereits einen Service Locator in diesem Bereich habe, beschleunigen gespeicherte Prozeduren die Entwicklung, da sie den Anwendungsentwickler von Datenbankproblemen befreien und umgekehrt. Dies hat einige Schwierigkeiten, aber es ist nicht so schwer zu tun.
Abfrage Wiederverwendung.
Oh und ein paar Dinge, die Sie in einem SP so gut wie nie tun sollten:
Nicht-Transaktionslogik. Sie haben die E-Mail gesendet, dass die Bestellung versandt wurde, aber die Transaktion wurde zurückgesetzt. Oder Sie warten darauf, dass der E-Mail-Server online geschaltet wird. Oder Sie setzen Ihre Transaktion zurück, nur weil Sie die nicht erreichen können E-Mail-Server ....
viele kleine Fragen, die locker aneinandergereiht und mit prozeduraler Logik übersät sind ...
quelle
Für wen arbeitest du?
Die Antwort kann davon abhängen, bei wem Sie angestellt sind, von welchem Beratungsunternehmen oder von welchem Unternehmen. Was für ein Unternehmen am besten ist, ist für ein Beratungsunternehmen oder einen anderen Softwareanbieter oft nicht am besten. zB Ein intelligentes Unternehmen möchte einen dauerhaften Vorteil gegenüber seinen Wettbewerbern haben. Im Gegensatz dazu möchte ein Softwareanbieter in der Lage sein, allen Unternehmen einer bestimmten Branche die gleiche Lösung zu den niedrigsten Kosten anzubieten. Wenn dies gelingt, entsteht für den Kunden kein Nettowettbewerbsvorteil.
In diesem speziellen Fall kommen und gehen Anwendungen, aber sehr oft lebt die Unternehmensdatenbank für immer weiter. Ein RDBMS verhindert in erster Linie, dass Junk-Daten in die Datenbank gelangen. Dies kann gespeicherte Prozeduren beinhalten. Wenn es sich bei der Logik um eine gute Logik handelt und es sehr unwahrscheinlich ist, dass sie sich von Jahr zu Jahr ändert, warum sollte sie dann nicht in der Datenbank vorhanden sein und intern konsistent bleiben, unabhängig davon, welche Anwendung für die Verwendung der Datenbank geschrieben wurde? Jahre später wird jemand eine Frage an die Datenbank haben, die beantwortet werden kann, wenn Junk daran gehindert wurde, in die Datenbank einzutreten.
Vielleicht hat das etwas damit zu tun, dass Ihr DBA für ein Beratungsunternehmen arbeitet. Je portabler sie ihren Code machen können, desto mehr können sie Code von Client zu Client wiederverwenden. Je mehr Logik sie in ihre App einbinden können, desto mehr ist das Unternehmen mit dem Anbieter verbunden. Wenn sie dabei ein großes Durcheinander hinterlassen, werden sie dafür bezahlt, es aufzuräumen, oder sehen das Durcheinander nie wieder. In jedem Fall ist es ein Gewinn für sie.
Für (viele) weitere Diskussionen auf beiden Seiten des Zauns lesen Sie die Diskussion zu Coding Horror . FWIW Ich lehne mich an die Seite der SP-Befürworter.
quelle
Es ist sehr schwierig, Datenbankmarken zu wechseln und dieselben gespeicherten Prozeduren zu verwenden.
Ihr Team hat entweder keinen DBA und niemand möchte etwas mit SQL zu tun haben.
Dies ist nichts weiter als ein Pisswettbewerb zwischen Programmierer und DBA.
quelle
IMO kommt darauf an. Gespeicherte Prozeduren haben ihren Platz, sind jedoch weder eine bewährte Methode noch sollten sie unbedingt vermieden werden. Ein intelligenter Entwickler weiß, wie eine bestimmte Situation richtig bewertet und festgestellt wird, ob eine gespeicherte Prozedur die Antwort ist. Persönlich bin ich ein Fan von ORMs (sogar von einfachen wie Linq to Sql) anstatt von gespeicherten Prozeduren, außer vielleicht für vordefinierte Berichte oder ähnliches, aber es ist wirklich von Fall zu Fall.
quelle
Es ist immer wieder problematisch, die Geschäftslogik mit verschiedenen Programmiersprachen auf verschiedene Ebenen aufzuteilen. Das Aufspüren eines Fehlers oder das Implementieren einer Änderung ist viel schwieriger, wenn Sie zwischen den Welten wechseln müssen.
Das heißt, ich kenne Unternehmen, die ziemlich gut abschneiden, indem sie die gesamte Geschäftslogik in PL / SQL-Pakete in der Datenbank einfügen. Das sind keine sehr großen Anwendungen, aber auch nicht trivial. sagen wir 20K-100K LOC. (PL / SQL ist für diese Art von System besser geeignet als T-SQL. Wenn Sie also nur T-SQL kennen, schütteln Sie jetzt wahrscheinlich ungläubig den Kopf ...)
quelle
Dies ist ein weiterer Punkt, der noch nicht erwähnt wurde:
Tools zur Codegenerierung und zum Reverse Engineering können mit gespeicherten Prozeduren nicht wirklich gut umgehen. Das Tool kann im Allgemeinen nicht sagen, was der Proc tut. Gibt der Proc eine Ergebnismenge zurück? Mehrere Ergebnismengen? Ruft es seine Ergebnismengen aus mehreren Tabellen und temporären Tabellen ab? Ist der Proc nur eine gekapselte Update-Anweisung und gibt nichts zurück? Gibt es eine Ergebnismenge, einen Rückgabewert und eine "Konsolenausgabe" zurück?
Wenn Sie also ein Tool verwenden möchten, um einen DTO- und DAO-Layer für Datenübertragungsobjekte automatisch zu erstellen (wie es der "Service Builder" von Liferay tut), können Sie dies nicht einfach tun.
Darüber hinaus können ORMs wie Hibernate nicht richtig funktionieren, wenn die Datenquelle ein SP ist. Der Datenzugriff ist bestenfalls schreibgeschützt.
quelle
Beim Solo-Programmieren kann ich nicht widerstehen , gespeicherte Prozeduren zu schreiben.
Ich benutze hauptsächlich MySQL. Ich habe zuvor keine objektorientierten Datenbanken wie PostGreSQL verwendet, aber was ich mit SPs in MySQL tun kann, ist, die Tabellenstruktur ein wenig zu abstrahieren. SP erlauben Sie mir diese primitive Aktionen zu entwerfen, deren Ein- und Ausgänge wird sich nicht ändern , auch wenn die Datenbank unter es nicht ändern.
Also habe ich eine Prozedur aufgerufen
logIn
. Wenn Sie sich einloggen, übergeben Sie immer nurusername
undpassword
. Das zurückgegebene Ergebnis ist die ganze ZahluserId
.Wenn
logIn
es sich um eine gespeicherte Prozedur handelt, kann ich jetzt beim Anmelden zusätzliche Arbeit hinzufügen, die gleichzeitig mit der ersten Anmeldung ausgeführt wird. Ich finde eine Reihe von SQL-Anweisungen mit eingebetteter Logik in einer gespeicherten Prozedur einfacher zu schreiben als die (aufrufende) Umgebungs-FETCH) -> (Ergebnis abrufen) -> (aufrufende Umgebungs-FETCH) -Reihe, die Sie ausführen müssen, wenn Sie Ihre Logikserverseite schreiben.quelle
Ich möchte auch darauf hinweisen, dass gespeicherte Prozeduren CPU-Zeit auf dem Server verwenden. Nicht viel, aber einiges. Ein Teil der im Arbeitsablauf geleisteten Arbeit kann in der App geleistet werden. Es ist einfacher, die App-Ebene als die Datenebene zu skalieren.
quelle
Ich stimme Mark zu, dass sich die Community seit einiger Zeit wirklich von gespeicherten Prozeduren entfernt hat. Während viele der Punkte, die das Original-Poster angesprochen hat, warum wir SPs verwenden möchten, auf einmal gültig waren, ist es eine Weile her und, wie ein anderes Poster sagte, hat sich die Umgebung verändert. Ich erinnere mich zum Beispiel, dass ein Argument für die frühere Verwendung von SPs die Leistungssteigerung war, die erzielt wurde, weil ihre Ausführungspläne vorkompiliert wurden, während dynamisches SQL aus unserem Code bei jeder Ausführung neu kompiliert werden musste. Dies ist nicht mehr der Fall, da die wichtigsten Datenbanken geändert, verbessert, angepasst usw. wurden.
Das heißt, wir verwenden SPs für mein aktuelles Projekt. Der Grund liegt einfach darin, dass wir neue Anwendungen auf einer vorhandenen Datenbank aufbauen, die noch ältere Anwendungen unterstützt. Daher ist es sehr schwierig, Schemaänderungen vorzunehmen, bis wir die alten Apps deaktivieren. Wir haben uns bewusst dafür entschieden, unsere neuen Anwendungen auf der Grundlage des für die Anwendung erforderlichen Verhaltens und der Regeln zu entwerfen und die SPs zu verwenden, um vorübergehend eine Schnittstelle mit der Datenbank zu bilden, wie wir es uns wünschen, und den SPs die Anpassung an das vorhandene SQL zu ermöglichen . Dies geht auf einen früheren Posting-Punkt zurück, bei dem SPs das Vornehmen von Änderungen auf Datenbankebene erleichtern, ohne dass Änderungen am Anwendungscode erforderlich sind. Die Verwendung von SPs als Implementierung des Adaptermusters ist für mich sicherlich sinnvoll (insbesondere in Anbetracht meines aktuellen Projekts).
Fwiw, wir beabsichtigen, die SPs zu entfernen, wenn das Schema aktualisiert wird. Aber wie bei allem anderen in der Unternehmensentwicklung werden wir sehen, ob das jemals passiert! [Grinsen]
quelle
Ich wollte nur einen kurzen Überblick darüber geben, wie ich die Verwendung gespeicherter Prozeduren empfehlen würde. Ich denke nicht, dass sie überhaupt eine schlechte Praxis sind, und wie andere gesagt haben, sollten sie in den richtigen Situationen verwendet werden.
Ich kann Probleme feststellen, bei denen das Schreiben von Prozeduren für verschiedene Anwendungen in der Funktionalität verwirrend werden kann und die Geschäftslogik der Anwendung voneinander trennt und dazu führt, dass die Datenbank auch unorganisierter und restriktiver wird.
Daher würde ich eine gespeicherte Prozedur in relationalen datenorientierten datenbankspezifischen Aufgaben verwenden. Mit anderen Worten, wenn für Datenbankoperationen Logik verwendet wird, die mit den Daten für eine Anwendung konsistent ist, kann eine gespeicherte Prozedur verwendet werden, um die Daten konsistent zu speichern (sinnvoll). Ich denke, gute Beispiele dafür sind: konsistente Protokollierung, konsistente Wartung, Arbeiten mit vertraulichen Informationen usw.
Andere Aufgaben, bei denen die Daten so bearbeitet werden, dass sie den Anforderungen der Anwendung entsprechen und dem starken Datenmodell der Datenbank entsprechen, sollten dann in einer anderen Ebene gespeichert werden, die die Geschäftslogik enthält. Kurz gesagt, datenbankspezifische Datenmanipulationen zur Konsistenz können gespeicherte Prozeduren verwenden, bei denen die Konsistenz über das Datenbankintegritätsschemamodell hinausgeht.
quelle
Gespeicherte Prozeduren "für mich" eignen sich für schreibgeschützte OLAP-Vorgänge, seltene Verwendung.
Für Geschäftsregeln, OLTP-Lese- / Schreibvorgänge bevorzuge ich Java-Anwendungsserver. Für eine einfache Codierung und eine weitestgehende Entlastung der CPU und des Speichers von den Master-DB-Servern. In diesem Setup ist der gesamte Code auf den Anwendungsservern nicht schwer zu überprüfen oder zu protokollieren und skalierbar.
Wichtig für mich ist, dass das Debuggen in der Business-Schicht einfacher ist als das Debuggen gespeicherter Prozeduren.
quelle
Neben der unnötigen Weitergabe von Geschäftslogik und der Bindung an einen bestimmten Datenbankanbieter bin ich fest davon überzeugt, dass eine Technologie auch für die vorgesehenen Zwecke eingesetzt werden kann. Eine Datenbank ist genau das, ein relationaler Datenspeicher. Verwenden Sie es zum Speichern von Daten, sonst nichts.
Wählen Sie Ihre Werkzeuge mit Bedacht aus und Sie sparen sich auf lange Sicht eine Welt voller Verletzungen.
quelle