Good Practice - Alles in Stored Procedures?

Ich hab da mal was gelesen::o)

Simplify: move code into database functions | Derek Sivers

Kurz um:

Datenbank konstant seit Jahren Postgresql.

Webserver variabel über die Jahre hinweg Perl/Ruby/Python/PHP/JavaScript(Client-Site).

:idea:Also warum die meist gleichbleibende Business-Logik immer neu implementieren bei Technologiewechsel, wenn man diese mit PL/SQL, Stored-Procedures, Constraints und Triggern in die DB verschieben kann? Webserver mit API-Aufrufen wird sehr einfach.

Aber lest selber. Ein gewisser Charme ist ja dabei.

Habe selbst schon Ansätze gesehen, die in diese Richtung gehen. Aber irgend etwas sträubt sich in mir dagegen.
Was ich gesehen habe (in Production):
Kein ORM-Framework sondern Plain SQL und viele SP.
Kein Webserver sondern direkter Zugriff auf die DB via Rich-Bitch-Fat-Client (Multiuser-Env)

Hat das ganze funktioniert: Im großen und ganzen.
War es schön: Definitiv nicht, bin zu wenig in PL/SQL, zudem noch sehr viel SQL-Code auf der Client-Seite.
Vorteile: Daten können angereichert werden (z.B. Erstelldatum, Änderungsdatum)
Der ein oder andere Roundtrip (Client - DB) kann gespart werden, wenn beim Anlegen zwei Datensätze eine 1-zu-1-Beziehung haben und der FK gleich mitaktualisiert werden kann.

Was haltet ihr von solchen Experimenten? Wenn es auch nur ein Gedankenexperiment sein sollte.

Schlechte Idee:

  1. gute PL/SQL oder T/SQL Entwickler sind selten, wer soll den Shit in der Zukunft warten?

  2. keine Möglichkeit die Performance zu steigern durch Middleware (man müsste dann gleich zu einem DB-Cluster wechseln, nur relevant ab einer gewissen Größe)

  3. sobald trigger eine stored proc aufrufen, die selbst wieder mehrere stored procs aufruft wird das kompliziert, transaktionsgrenzen, fehlersuche, etc.

  4. komplexe Verarbeitung ist in Hochsprachen wie Java einfacher zu realisieren als im relativ simplen PL/SQL etc.

  5. vollständiger, totaler Vendor Lock-In bezüglich der Datenbank

  6. Management of Change: größere Änderungen in der komplexen Business-Logik werden viel schwieriger im Spaghetti-Datenbank-Skript-Universum

  7. Export/Migration der DB schwierig: im Vergleich zu flachen „Tabellen=Daten“ muss man viel Zeug herumschleppen

  8. ein paar Jahre später weiß kein Schwein mehr, warum dieser update-trigger immer anspringt und geheimnisvolle Sachen in der Datenbank macht

Fazit: Wenn die Datenbank fest ist und gute Entwickler langfristig vorhanden sind - könnte man schon machen. Hängt davon ab, was man will: direkt http/JSON Anfragen an das RDBMS sind heute möglich, und das Ergebnis als JSON zurückschicken auch - wozu dann überhaupt noch Middleware?

Disclaimer: ich mach das ständig - eine Stored Proc ist schneller geschrieben als Anwendungscode in Java, man kann Änderungen oft direkt (und schnell) hot hot hot in der DB durchführen ohne die Clients anzufassen, nach mir eh die Sintflut usw.

Wenig. Unwartbare schrottige riesige SQL-Wüsten werden entstehen. Das klassische Middleware-Konzept, bei dem in der DB nur die Daten sind und für den Rest eine gut dokumentierte (Witz) Anwendungslogik in einer Hochsprache umgesetzt wird ist meiner Meinung nach die bessere Investition für einen Kunden mit gewissen Ansprüchen an Wartbarkeit, Zukunftssicherheit, etc.

Ich arbeite an genau so einer Anwendung:
Wichtige Fachlogik steckt in Triggern und Stored-Procedures in der DB. Der Fat-Client greift direkt auf die DB zu.
Der größte Vorteil dieser Variante ist, dass Berichtigungen oder Änderungen der Fachlogik zentral in der DB gemacht werden können, ohne neue Clients auszurollen.
Das bekommt man aber auch mit einer 3-Tier-Architektur.

Der für mich größte Nachteil ist: PLSQL lässt sich schlecht UnitTesten, weil mocking de-fakto unmöglich ist. (OK, man könnte die kollaborierenden Packages für den Test durch Mocks ersetzen, aber das würde die Laufzit der Tests erhöhen, was dann auch dem Konzept von UnitTests zuwider läuft. Außerdem gibt es ja auch im getesteten Package funktionen, die man als Support benötigt, die aber grade nicht im Testfokus stehen.

Das Problem mit dem Vendor Lockin sehe ich nicht im Vordergrund. Das zentrale Motiv, den DB-Herstelle beizubehalten ist doch ehr die Datenmigration, die man sich sparen möchte, so wie das im TO schon angedeutet wurde.

bye
TT

Ja, das mit dem Vendor-Lock-In kann man entspannt sehen: bei großen Installationen wird da eh nie gewechselt - klar. Außer wenn die Bude vom amerikanischen Konzern Hedge Operations Company übernommen wird und alles umgekrempelt werden muss :slight_smile:

Schreibst du ja selbst, dass das auch der größte Nachteil ist: wenn die Datenbank mal im 100GB oder TB Bereich läuft, ist es praktisch unmöglich, eine funktionierende Off-Line Testversion vorzuhalten.

Es gibt eine verkleinerte Testversion, dort spielt man eine neue StoredProc ein und testet ein bisschen zusammenhanglos mit den Fat-Clients und/oder (besser) einer Testsuite.

Dabei fällt mir noch ein Nachteil ein: durch das Aufeinandertürmen immer neuer Stored Procs entstehen bei mir manchmal gewaltige Transaktionen die viele, viele Daten verändern - und bei einem Rollback steht der ganze Bims dann eingefroren da und ich geh gemütlich eine rauchen.

Frage eines Consultants: Wie sieht die Dokumentation aus? Ist die aktuell? Wer arbeitet daran?

wenn man dermaßen wie über Perl/Ruby/Python/PHP/JavaScript schwankt, dann ist die DB Postgresql ohne Zweifel felsenfest?

na, kommt im ernsten Maßstab eh nicht in Frage,
simple Kleinigkeiten kann man damit vielleicht umsetzen, ja, aber die einzeln zu portieren würde auch keine bedeutende Zeit kosten

der Hauptteil einer anspruchsvollen Anwendung besteht aus komplizierten Konstrukt dutzender Klassen, Interface, Enums,
variabel über Parameter, aktuelle Einstellungen, aktuelle User, konkrete Eingaben usw. gesteuert,

da werden zur Verarbeitung MB-große Libraries oder eben (im Java-Fall) die ganze Java-API eingesetzt, man denke nur an simple Listen und Maps,
theoretisch durchaus alles irgendwo anders abzubilden, wenn nur dort genug Programmier-Umgebung vorhanden,

aber dann kann man auch kaum mehr von einem Perl/Ruby/Python/PHP/JavaScript- oder eben Java-Programm reden,
sondern programmiert in der DB, falls man das möchte bitte,
die DB kann aber nicht selber der WebServer sein? soweit also noch nicht…, diese Beschränktheit sollte zu denken geben

eine IDE gibts auch nicht, keine Klassen, keine Verbung, keine Annotations, kein Exception-Handling usw.?
ziemlich beschränkt alles, nicht gerade das worin man wichtigen Code umsetzen sollte

die Programmiersprache zu wechseln ist nun mal fatal, da hilft alles nix, außer evtl. temporär verschiedene Programme
in verschiedenen Sprachen gleichzeitig laufen und kommunizieren zu lassen

innerhalb einer Sprache (wie Java :wink: ) gibt es noch häufig genug den Wechsel der Frameworks,
dabei sollte man darauf achten, die wichtigen Logikklassen soweit wie möglich unabhängig zu gestalten,
wiederverwendbarer Code

Ich kannte so einige Anwendungen, die Logik auf DB-Seite hatten, sei es, weil es angeblich performanter war, sei es, weil es einfacher schien. Selbst so naheliegende Sachen wie die Nutzung von DB-Replikation für ein mehr oder weniger verteiltes System haben im Endeffekt immer ordentliche Schwierigkeiten gemacht. Von den Problemen bei einer Migration ganz zu schweigen. Für mich gilt deshalb die Leitlinie: Je dümmer die Datenbank (und der Daten-Layer), um so besser.

[quote=Landei]Je dümmer die Datenbank (und der Daten-Layer), um so besser.[/quote]Bei einigen sachen ist logik in der DB aber durchaus sinnvoll: Beispielsweise Archivierung.

In unserer Anwendung werden die Daten nie gelöscht, sondern nur als “gelöscht” markiert. Wenn man die Clients nicht gegen die Tabellen selbst sondern gegen Views arbeiten lässt kann das OR-Mapping-Framwork einen gewöhnliches delete from view where… absetzen und der View-Trigger kümmert sich um die Archivierung. Gleiches gilt für Updates und Inserts wobei der Trigger dann sogar weitergehende Konsistenz-Prüfungen machen kann.

Also mein Fazit: Logik in der DB ehr nein, aber…

bye
TT

[quote=Timothy_Truckle]Bei einigen sachen ist logik in der DB aber durchaus sinnvoll: Beispielsweise Archivierung.

In unserer Anwendung werden die Daten nie gelöscht, sondern nur als „gelöscht“ markiert. Wenn man die Clients nicht gegen die Tabellen selbst sondern gegen Views arbeiten lässt kann das OR-Mapping-Framwork einen gewöhnliches delete from view where… absetzen und der View-Trigger kümmert sich um die Archivierung. Gleiches gilt für Updates und Inserts wobei der Trigger dann sogar weitergehende Konsistenz-Prüfungen machen kann.

Also mein Fazit: Logik in der DB ehr nein, aber…[/quote]

Hmpf. Die Welt ist doch so schon kompliziert genug.

Java-Programmierer schreiben am OR-Framework, SQL-Profis bearbeiten die Trigger - wie viel Arbeit man aus einem einfach ALTER TABLE ADD COLUMN rausquetschen kann, schon fantastisch.

Sehe ich auch so. Wenn ich nicht gerade SQL-Hacking betreibe :slight_smile:

[QUOTE=Timothy_Truckle;118593]Bei einigen sachen ist logik in der DB aber durchaus sinnvoll: Beispielsweise Archivierung.

In unserer Anwendung werden die Daten nie gelöscht, sondern nur als “gelöscht” markiert. Wenn man die Clients nicht gegen die Tabellen selbst sondern gegen Views arbeiten lässt kann das OR-Mapping-Framwork einen gewöhnliches delete from view where… absetzen und der View-Trigger kümmert sich um die Archivierung. Gleiches gilt für Updates und Inserts wobei der Trigger dann sogar weitergehende Konsistenz-Prüfungen machen kann.

Also mein Fazit: Logik in der DB ehr nein, aber…

bye
TT[/QUOTE]

Ich weiß, dass es nicht für alle Anwendungsfälle passt, aber du solltest dir mal Hibernate Envers anschauen. Wenn es passt, ist es sehr elegant. Vor allem gefällt mir, dass die Ursprungstabellen dabei “sauber” bleiben.

[QUOTE=Timothy_Truckle;118593]Bei einigen sachen ist logik in der DB aber durchaus sinnvoll: Beispielsweise Archivierung.

In unserer Anwendung werden die Daten nie gelöscht, sondern nur als „gelöscht“ markiert. Wenn man die Clients nicht gegen die Tabellen selbst sondern gegen Views arbeiten lässt kann das OR-Mapping-Framwork einen gewöhnliches delete from view where… absetzen und der View-Trigger kümmert sich um die Archivierung. Gleiches gilt für Updates und Inserts wobei der Trigger dann sogar weitergehende Konsistenz-Prüfungen machen kann.

Also mein Fazit: Logik in der DB ehr nein, aber…

bye
TT[/QUOTE]
Für Dein genanntes Problem gibt es genug Lösungen, die nicht in der DB laufen müssen. Vorteile in Deinem genannten Beispiel kann ich nicht sehen. Es teilt Businesslogik in unterschiedliche Technologien, die von (häufig) unterschiedlichen Personen gewartet werden. So entsteht „Magie“ in der Anwendung. :slight_smile:

Eine solche Meinung von einem Softwareentwickler finde ich sehr ungewöhnlich. Typischerweise wird diese von beinharten DB-Admins vertreten, die ihre Relevanz sichern wollen.

Das angebliche Argument Simplizität kann ich nicht nachvollziehen. Die meisten ORMs sind auf CRUD getrimmt; Support für Stored Procedures kam z.B. bei JPA erst mit der 2.1 rein und nach Beispielen, die ich ergoogelt habe, ist es ein Krampf, diese zu benutzen.

Ich würde Stored Procedures dann einsetzen, wenn mehrere Operationen immer zusammen ausgeführt werden müssen und die Anwendung so viele Queries erzeugt, dass die Roundtrips zur Datenbank zum Flaschenhals werden. Dies von Anfang an so zu machen, wäre premature optimization.

Beispiel: Oracle stellt ein Java-DB-SDK bereit mit dem sehr einfach alles in Java-Code erstellt werden kann. DB lernt Java. Siehe auch NoSQL mit JS als Beispiel. Gibts nicht könnte aber kommen.
OT: MS ging ja mit Linq in die entgegengesetzte Richtung.

Ack. Manchmal vielleicht sogar eine gute Lösung. (z.B. Inhouse Lösung für eine Firma bei denen Server in Wert 1 steht und in Werk 2 über schlechte Leitung darauf zugegriffen werden soll. Eine Replication in Werk 2 z.B. als nur lesend. Synchronization zum Master durch DB könnte eine gute Lösung sein).

Schwierig eine Aussage zu treffen. Wenn die Trigger notwendig sind, dann bekommt man auch auf mehrere Statements die abgeschickt werden müssen. Dann muss man die Fehlerquelle auf der Java-Seite suchen. Bei mehreren einzelnen Requests auch nicht prikelnd.

Ack. könnte sich aber zu einem Standard entwickeln. (Ja, ist sehr optimistisch gedacht und wohl eher friert die Hölle zu).

Ack. ist aber immer schwierig.

Sehe ich jetzt nicht so.

Dokumentation? Selbst bei Java-Code wird man raten was das ganze soll.

:lol:Clients anfassen ist immer nervig. Erst recht, wenn man keinen vernünftigen Update-Mechanismus nutzt. Eine Idee die mir hierzu vorschwebt ist z.B. Rhino Script Engine einzubetten und einen Teil der Logik in JS zu schreiben und aus der DB Laden. Aber das ist eine andere Geschichte. @Bleiglanz ich möchte dich nicht trollen, deine Argumente (1,3,4,5) treffen zu können aber jederzeit geändert werden, wenn man möchte.

@Slater auch in Java entwickeln sich die Frameworks weiter, Servlet/JSP/Wicket/GWT/REST/SPRING MVC/JSF1.x/JSF2.x und die typische Datenhaltung von Handgestrickt hin zur JPA ist auch nicht gerade unüblich. Da kann schon einiges an Bewegung drinstecken.

Persönlich tendiere ich auch zu dummer DB und einem ausgereiften ORM. Allerdings sehe ich auch die ein oder andere Verlockung rufen, hier und da mal was direkt in der DB auszuführen und manipulieren zu lassen. Ein ORM ist eben auch begrenzt und begrenzt damit auch das, was man machen kann.

OT: Der Thread hat schon einiges an Flamewar potential.

OT2: Mit Hazelcast, wenn wir in Zukunft alle nur noch mit In-Memory-DB-Clustern arbeiten wird sich das ganze eh erübrigen;)

Oh ich sehe Hazelcast, wer hat mich gerufen? :smiley:

Also ich finde Fehlersuche und Debugging (gerade in modernen IDEs) auf der Java-Seite wesentlich einfacher

Ja, aber da ist das Raten einfacher :slight_smile:

Gestern in meiner Blogroll:** Christ, how deep down this fucking rabbit hole are we going? **

fand ich recht witzig: It’s The Future | The Circle Blog

[QUOTE=Bleiglanz]Gestern in meiner Blogroll:** Christ, how deep down this fucking rabbit hole are we going? **

fand ich recht witzig: It’s The Future | The Circle Blog[/QUOTE]

LOL!