Batching bei PostgreSQL

AnfängerDB

Benutzer
Beiträge
19
Hallo Community,

ich nutze Asp net Core(C# also .net), das Entity Framwork und als Datenbankmanagementsystem PostgreSQL,
(ein Teil) meiner Architektur ist ein Repository Pattern. Es kann sein das ich eine größere Menge an Datensätze(10-200+) einfügen oder aktualisieren möchte/muss.

Ich möchte dazu Batching nutzen wie hier beschrieben, aber macht dies bei der Datenmenge bei PostgreSQL sinn ? Denn ebenso kann es sein das ich auch nur Spalte einfügen/updaten muss, dies kann ich nicht vorhersagen, da mein Back-End an einen Web-Service gekoppelt ist und deren User unterschiedliche Mengen an Daten ändern können.

Hat jemand Erfahrungen mit Batching im PostgreSQL Kontext ?

Über nette Antworten würde ich mich sehr freuen :)

Danke im vorraus
 
Werbung:
Hat jemand Erfahrungen mit Batching im PostgreSQL Kontext ?

Mir ist nicht ganz klar, was dort im Artikel gemeint ist, aber ein paar Gedanken:

  • fasse zusammenhängende Statements in einer Transaktion zusammen. Einerseits wegen Datenkonsistenz, andererseits ist das dann auch schneller
  • vermeide Schleifen in SQL
  • via wCTE und der RETURNING - Anweisungen kannst Du z.B. erzeugte id's im selbern Statement für weitere INSERT's verwenden
 
Die Sache ist, ich bekomme eine Collection von dem Webservice und ich muss durch diese durch Iterieren, um an die einzelnen Einträge zu kommen, um diese dann abzuspeichern muss ich die Save Methode in die Foreach schleife schreiben z.B wie in dem Beispiel (also im Bezug auf das Iterieren), aber ich prüfe noch vorher auch ob es den Eintrag in der Datenbank gibt, wenn es ihn gibt dann Update ich.
 
ich prüfe noch vorher auch ob es den Eintrag in der Datenbank gibt, wenn es ihn gibt dann Update ich.
geht einfacher:

Code:
edb=*# create table foo(id int primary key, val int);
CREATE TABLE
edb=*# insert into foo values (1, 10) on conflict (id) do  update set val = excluded.val;
INSERT 0 1
edb=*# select * from foo;
 id | val
----+-----
  1 |  10
(1 row)

edb=*# insert into foo values (2, 20) on conflict (id) do  update set val = excluded.val;
INSERT 0 1
edb=*# select * from foo;
 id | val
----+-----
  1 |  10
  2 |  20
(2 rows)

edb=*# insert into foo values (2, 40) on conflict (id) do  update set val = excluded.val;
INSERT 0 1
edb=*# select * from foo;
 id | val
----+-----
  1 |  10
  2 |  40
(2 rows)

edb=*#
 
Verstehe ich nicht, was hat eine Collection / Webservice mit SQL zu tun?
Und wo ist das Problem, 200 Datensätze einzufügen oder zu aktualisieren (bei eindeutigen Schlüsseln)?
Oder kommen die Daten nur über einen Service rein und gehen per SQL raus?

zu "batching" (ala MS)
Unter dem Vorbehalt, dass ich es nicht verstanden habe, aber was Dein erster Link zeigt ist m.E. eine typische MS Unart. Es wird irgendeine Verschlimmbesserung in die Kommunikation eingebaut, die für irgendwas helfen soll (schlappe Server schonn?), hier offenbar (muss ich lachen? Und wenn ja wegen des Inhalts oder der Übersetzung?):
Updates bis zu 4 Datensätze laufen nicht besser damit, dann ab 5 aber schon, danach aber ab 42(!) wieder nicht mehr und dann läuft es wieder anders..
Weitere Links habe ich mir nicht angeschaut. (Ich sehe schon vor mir, wie Du Code schreibst, der die Anzahl der Updates abwägt und dann vollständig, teilweise oder gar nicht arbeitet, je nach Zumutungsgrad für die Infrastruktur.) Plus MS hat wieder irgendwo einen Fuß in der Tür mit irgendeiner Lib, einem Framework, .. , eine unnötige Abhängigkeit geschaffen und kann dann wieder Schulungen, Nachschulungen, Zertifizierungen und Produktupdates oder alle 4 Jahre ganz neue Konzepte und Software verkaufen (jetzt neu: bis zu 45 Datensätze in einem Schwung!!!11!).
 
Verstehe ich nicht, was hat eine Collection / Webservice mit SQL zu tun?
Und wo ist das Problem, 200 Datensätze einzufügen oder zu aktualisieren (bei eindeutigen Schlüsseln)?
Oder kommen die Daten nur über einen Service rein und gehen per SQL raus?
.
Ich bekomme von einen Web-Service nunmal eine Collection (IDataItemCollection) deren Ihnalt ich in einer DB abbilden möchte und so eine Collection kann bis von 0- 200 Einträge enthalten. Die ich möglichst schnell verarbeiten möchte
Zum Problem ich habe nunmal diese Anleitung bei MS gefunden und wollte daher wissen wie sinnvoll es ist das Batching händisch zu einzustellen. Noch habe ich keine Abwägungen zu Updates geschrieben oder der gleichen.
Man muss jetzt nicht gemein werden. Ich frage deshalb lieber nach bevor ich mist baue^^
 
Nein, ich werde nicht gemein und bin es nicht.

Hast Du schon mal 200 Datensätze in einem Insert Script in eine DB eingefügt? Was glaubst Du was passiert? Probier es mal aus.
Es passiert nichts, außer das was soll. Ein paar Millisekunden und es ist fertig.

Um es noch mal klar zu sagen:
Du hast kein Problem, mach einfach Deine 200 Inserts.
 
Es passiert nichts, außer das was soll. Ein paar Millisekunden und es ist fertig.

Jein. Möglicherweise soll gelten, daß entwerder ALLE oder KEIN Insert passiert, nicht aber x erfolgreiche und 200-x gescheiterte Inserts. 200 einzelne Inserts sind 200 einzelne Transaktionen, jeweils mit einem fsync() auf das WAL.
200 Inserts in EINER Transaktion ist dann auch nur 1 fsync() auf das WAL. Prüfung, ob es ein Insert oder ein Update werden soll, kann man auch unerschiedlich realisieren. Siehe auch #2 und #4.
 
Jein. Möglicherweise soll gelten, daß entwerder ALLE oder KEIN Insert passiert..
Ja, er könnte einen anonymen Block nutzen, um eine gesamte Transaktion zu erhalten.
Vielleicht gibt es ja in .net core sogar eine Script Komponente.

Oder er überträgt die Collection Daten an eine Postgres SP, die das kleinteilig verarbeitet.
 
Also für ein paar hundert Datensätze würde ich mir überhaupt keine Gedanken machen, das irgendwie in kleinere Portionen zu zerlegen. Einfach ein INSERT mit der Anzahl der Datensätze ausführen- fertig.
Wenn man wirklich z.B. Fehler wegen doppelter Datensätze ignorieren will, mit ON CONFLICT arbeiten (siehe Beispiel von akretschmer).

Ich würde erst ab ein darüber nachdenken, so was zu zerlegen wenn das in die "zig-tausende" geht.
Dann halt eine Transaktion und pro INSERT ein paar tausend Datensätze übertragen.
 
Genau, das versuche ich ja zu vermitteln, aber es kommt vielleicht nicht an.
Einfach die Datensätze einfügen (oder updaten), ohne merkwürdige MS add on Libs.

Vielleicht arbeitet man ja auf einem schwer ausgelasteten Server oder zusammen mit hunderten anderen Usern, die das gleiche machen oder das ist eine Webapplication, mit hunderten Sitzungen oder es gibt ungewöhnlich viele Indizes auf riesigen Zieltabellen ... dann sieht es vielliecht anders aus und man müsste genauer schauen.
 
Einfach die Datensätze einfügen (oder updaten), ohne merkwürdige MS add on Libs.
Nicht böse sein über diese unnötige, dumme und auch freche Frage ;-) aber was spricht denn gegen ein ORM-Mapper (wie z.B Hibernate , EF, ...) ? Z.B mit Hibernate (Java) bin ich bisher immer gut gefahren. Ich habe z.B eine Erweiterung zu EF Core entdeckt in dem es auch Bulk-Insert gibt, in StackOverflow wird dieser im sehr propagiert wenn es um Geschwindkeit geht^^
 
ORM = Obfuscated Relational Model

Ich kann nur aus meiner Erfahrung berichten, dass ungefähr 3/4 aller Performance Probleme mit der Datenbank im Java Umfeld auf Hibernate zurückzuführen sind. Entweder weil Hibernate grottenschlechtes SQL generiert (vor allem wenn das unsägliche Criteria API verwendet wird) oder weil Hibernate falsch konfiguriert war und zig überflüssige Abfragen ausgeführt hat, für etwas was eigentlich in "plain" SQL mit 1 bis max. 2 Abfragen gemacht werden kann. In den meisten Fällen werden dann die HQL Abfragen in native Queries umgeschrieben und schon war die Performance wieder in Ordngun

Batching in Hibernate hat auch seine Probleme. Mein letzter Wissensstand ist, dass das z.B. nicht klappt wenn man identity (oder die alten serial) Spalten verwendet.
 
Werbung:
Ich betreue bei uns intern die Entwickler-Teams für die einzelnen Projekte in Fragen und Problemen rund um relationale Datenbanken, deswegen landet das immer bei mir wenn's Probleme gibt.

Die Einstellung, dass Hibernate "alle Probleme" löst findet sich nur nur in den Tutorials und Unis. Auch eingefleischte Java Entwickler und Architekten sehen in der Datenbank in der Regel einen "dummen" Datenspeicher. Etwas besser als ein Flat-File, aber nicht wirklich mehr ("Wir brauchen keine Foreign keys! Die Anwendung kann das viel effizienter lösen").
Die wollen sich mit der Thematik gar nicht auseinandersetzen und SQL lernen und verstehen schon gleich zehnmal nicht.

Bis es dann das erste Mal kracht und ich ihnen zeige, was man alles mit SQL so anstellen kann. Ich sollte mal ein Performance Problem lösen bei dem das Auslesen eines Produktkataloges (=hierarchische Datenstruktur) in der Datenbank mehrere Minuten gedauert hat (die Tabelle war nicht groß, das waren nur ein paar Tausend Produkte). Es hat sich rausgestellt, dass die Entwickler eine Abfrage für alle Einträge einer Kategorie implementiert hatten (Hibernate Mapping einer Entity). Dann haben sie das Ergebnis genommen, alle Unterkategorien dafür extrahiert und für jeden Unterkategorie die Methode wieder rekursiv in Java aufgerufen haben. Da wurden dann schlussendlich zig-tausende von Abfragen ausgeführt - jede einzelne nur ein paar Millisekunden lang, aber in der Summe dann zu lang. Und offensichtlich hat Hibernate dann bei jedem rekursiven Aufruf wieder eine Verbindung aus dem Connection Pool genommen, so dass der ganz schnell zu klein wurde.

Ich habe das mit einer rekursiven Abfrage gemacht, die hat dann den kompletten Baum in einer halben Sekunden geladen (und brauchte auch nur eine Verbindung in der Datenbank).

Das Problem mit Tutorials im Internet ist, dass sie fast immer einfache, wenig komplexe Beispiele nehmen (um die Konzepte zu verdeutlichen) die in der Realität so aber nie vorkommen. Und was mit ein paar tausend Datensätzen noch prima klappt, funktioniert halt mit zig-Millionen nicht mehr so einfach.
 
Zurück
Oben