Zeilen in Datenbank schreiben mit Variable

  • .NET (FX) 4.5–4.8
  • VB.NET

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von 0ptix.

    Zeilen in Datenbank schreiben mit Variable

    Hallo zusammen,

    Was ist die SItuation?
    Ich habe eine Anzahl von X Objekten mit Properties. X ist nicht bekannt. Ich weiß nur dass es etwas mehr als 500.000 sind
    Was habe ich bis jetzt? Momentan ist es mir möglich, die Objekte in eine SQL Tabelle zu schreiben da ich alles in 100er Blöcke abarbeite. (zum einfacherem rechnen, ist auch erst mal egal)
    D.h. Ich lese die Daten aus, schreibe das in eine DataTable, gleiche das mit meinem Block-int ab und wenn dieser erreicht ist werden die Objekte in die SQL-Tabelle geschrieben
    und die Datatable wieder geleert. Klappt alles einwandfrei..
    Was ist jetzt mein Problem? Ich kann nur ganzzahlen schreiben, d.h. dass wenn z.B. 521.235 Objekte da wären dann würden mir die 35 Fehlen (35 < 100).
    Was waren meine Ansätze? Ich habe versucht mit "<=" zu arbeiten, aber da ja auch 1 kleiner als 100 ist würde immer die 1 genommen werden, was wiederum dafür sorgt dass 1. die Performance absoluter Mist ist und 2. zu viel WriteToServer Anfragen auftauchen,
    was wieder rum dazu führt dass die Connection zusammenbricht. Ein weiterer Ansatz war, alle objekte zu zählen, die wurzel daraus zu ziehen und das dann als "Block" zu setzen -> was ebenfalls Performance technisch absoluter quatsch ist und außerdem vermutlich 10x so lange dauert.

    Ich bin mir ziemlich sicher dass es mit irgendeinem Operator in der if-Condition geht aber ich komm einfahc nicht drauf. Evtl. hat jemand noch ne bessere Idee

    Thead aus Tipps und Tricks verschoben ~ EaranMaleasi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „EaranMaleasi“ ()

    Ach so, ja. Mir gehts eigentlich viel mehr darum ob jemand eine Idee hat wie ich das umsetzen kann.
    Also einen Gedanken wie man da ran gehen kann, das ist ja unabhängig von meinem Code an der Stelle :)
    Leider bin ich auch grade nicht in der Lage den Code hier rien zu stellen...
    Das Problem ist dass ich nicht weis wieviele Elemente "übrig" sind. D.h ich kann keine Zahl definieren. Mitt "kleiner Gleich" komm ich nicht weit. "ein Between" macht auch keinen Sinn, die Zahl kann ja immer anders sein.
    Leider kann ich auch nicht einfach alles in einer Variable speichern, das dreht mir den RAM zu hoch und die auslastung ist gigantisch, deshalb die BLockweise abarbeitung
    Eine Idee also...

    Nun da wir eh schon mit Objekten arbeiten, würde ich den Weg über eine DataTable komplett verwerfen, und entweder mit einem kleinen ORM Framework wie Dapper arbeiten, oder sogar komplett Hand anlegen. Dadurch bekommst du die höchste Performance was inserts angeht.

    Aber nochmal von Anfang. Mit Json.NET würde ich die Objekte einlesen, sodass sie, leider, komplett im RAM vorliegen (vielleicht gibts ja auch einen Weg die Stück für Stück einzulesen, müsste ich recherchieren).

    Dann wird die Connection geöffnet, eine Transaktion gestartet und der INSERT Command festgelegt. Nun gehe ich mit For durch die Liste durch, weise die Werte des Objektes den Parametern des commands zu, und führe den Befehl aus.
    Alle i%1000 == 0 wird dann ein Commit durchgeführt.
    Im Falle dass etwas schief geht, kann dann Rollback durchgeführt weden.
    Nach der Schleife wird dann nochmal ein extra commit durchgeführt, da es sehr wahrscheinlich ist, dass wir eine Anzahl von Objekten haben, die sich nicht glatt durch 1000 Teilen lässt.

    Nun noch Ordnungsgemäß Command, Transaction und Connection Disposen (am besten ist das alles sowieso in Usings gepackt) und schon sollte das ruck zuck durchlaufen.

    Dadurch solltest du Insertgeschwindigkeiten am "Hardwarelimit" erreichen.

    0ptix schrieb:

    Das Problem ist dass ich nicht weis wieviele Elemente "übrig" sind.
    Verstehe ich nicht.
    Du kannst ermitteln, wann deine DataTable 100 Datensätze enthält, und sie dann "abschicken".
    Aber du kannst nicht ermitteln, wieviele es sind, wenn es weniger sind?
    Sonderbar.
    Schreib deinen Code so, dass du das kannst.

    @HenryV: Ja, gute Idee - das Stichwort ist also: "LetzterDatensatz" - also dass ermittelt wird, ob kein weiterer Datensatz mehr kommt, und das soll das "Abschicken" ebenso auslösen wie es derzeit die Anzahl 100 tut.

    @EaranMaleasi: Wenn ich recht erinnere kann zumindest SqlServer eine DataTable als Argument einer StoredProcedure entgegennehmen.
    Das ist eine feine Art eines Bulk-Inserts und glaub schneller als ein per Schleife vielgefeuertes InsertCommand.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Ich weis dass eine Zahl existiert die größer als eine halbe Million ist aber ich weis nicht was hier steht: 500.XXX. Also brauch ich irgendwas um diesen einen letzten "Block" in meine Datatable zu schreiben. Von dem ich nicht weis wieviele Objekte darin enthalten sind.
    Allerdings wird nur immer in die Datatable geschrieben wenn die Anzahl der Objekte 100 ist. Wenn ich aber 100 nie erreiche wird auch nix geschrieben.

    Also [X-Anzahl Objekte] -> Abfrage in 100er Blöcken -> bei erreichen von 100 Objekten -> schreiben in Datatable -> Datatable in SQL Übertragen(ich nutze BulkCopy) -> Datatable leeren. (und dann wieder von vorne bis alle Objekte in der SQL Tabelle sind)
    jetzt haben wir z.b 523.123 Elemente. Das macht dann 5.231 Datensätze die in die SQL Tabelle eingetragen werden. Aber wo sind die restlichen 23? Nicht da weil "23 < 100" -> also wird der Punkt nicht erreicht und die datatable wird nicht übertragen.

    Wegen dem Stichwort "Letzter Datensatz" wie kann ich das definieren oder woher weis ich das wann dieser letzte Block kommt?
    Or- / OrElse bringt mir nichts weil ich die Condition für das letzte nicht kenne, also die Zahl.Klar könnte ich die Objekte davor alle zählen lassen aber
    dann muss ich ja durch alles 2x durchloopen und in der zwischenzeit kann ja wieder was neues dazu gekommen sein, also fehlt mir trotzdem wieder was am schluss.
    Daher macht das auch keinen Sinn.

    0ptix schrieb:

    woher weis ich das wann dieser letzte Block kommt?
    Das hängt davon ab, wie du die Daten einliest.
    An deim Code könnte man vielleicht erkennen, wie das geschieht.

    0ptix schrieb:

    Allerdings wird nur immer in die Datatable geschrieben wenn die Anzahl der Objekte 100 ist. Wenn ich aber 100 nie erreiche wird auch nix geschrieben.
    wie ist das bewerkstelligt?
    Das ist ja schon irgendwie ärgerlich.
    Jetzt haben wir 13 Posts, 3 Leute, zwei Stunden gebraucht, um dir aus der Nase zu ziehen, dass du mit einem WebRequest arbeitest.
    Und ich vermute, der antwortet einfach nicht, wenn man ihm mehr Datensätze abfragt, als auf der anderen Seite verfügbar sind.

    Ich lerne daraus, dass ich mich auf "Code zeigen hat kein Sinn" nie wieder einlasse - weil im Code hätten wir das sofort gesehen.

    Für das Problem - wenn ich es denn nun richtig verstanden habe - weiss ich auf die Schnelle auch keine Lösung, denk ich vielleicht später mal drüber nach.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Doch er antwortet schon, das ist es ja. Ich bekomme auch die User, das ist alles kein Problem. Nur ich habe das Problem mit der Datatable.
    Für den Code ist es unerheblich ob Webrequest, Excel, XML, oder meinetwegen auch Word Dokument. Sogar die Sprache dafür ist egal, ich frage ja nur nach der Logik
    Objekt bleibt Objekt und ich will einfach nur wissen wie es mir möglich ist die Objekte zwischen Nr. 101 und Nr. 199 in die DataTable zu schreiben. Mehr will ich ja gar nicht.

    ganz Banal gesagt:
    get-Objects
    if objectAnzahl = 100 then write to Datatable
    write to sql
    Empty DataTable

    jetzt haben wir nur noch 5121XX Objekte.
    Dann machen wir das ganze so lange bis nur noch XX Objekte da sind.
    Aber wie kann ich das jetzt der if-Condition sagen "Hey jetzt sind es keine 100 mehr sondern nur noch weniger, ich hab zwar null plan wieviele aber das musst du rausfinden, schreib mir das in meine DataTable und mach so weiter"

    MOmentan brauche ich für 10.000 Objekte etwa 20 Sekunden mit einer Abfrage von 100
    Mit einer Abfrage von 1 brauche ich für 10.000 Objekte etwa 35 Minuten.
    35 Minuten x 50.000 = verdammt lange

    0ptix schrieb:

    Aber wie kann ich das jetzt der if-Condition sagen "Hey jetzt sind es keine 100 mehr sondern nur noch weniger, ich hab zwar null plan wieviele aber das musst du rausfinden, schreib mir das in meine DataTable und mach so weiter"
    Lass die if-Condition am Schluss weg, und programmiere einfach:
    "Hey jetzt sind es keine 100 mehr sondern nur noch weniger, ich hab zwar null plan wieviele aber das musst du rausfinden, schreib mir das in meine DataTable und mach so weiter"

    0ptix schrieb:

    Ja wenn ich das mache dann schreibt er alles einzeln. das is ja genau mein Problem.
    Nein, wenn du das machst, macht er, was du willst (oder zumindest hier sagst, dass du es willst).
    Wenn er was anderes macht, hast du einen Fehler in dem Code, von dem du denkst, dass er macht, was du willst.

    ErfinderDesRades schrieb:

    "Hey jetzt sind es keine 100 mehr sondern nur noch weniger, ich hab zwar null plan wieviele aber das musst du rausfinden, schreib mir das in meine DataTable und mach so weiter"

    0ptix schrieb:

    Ja wenn ich das mache dann schreibt er alles einzeln.

    Das ist doch Blödsinn.

    Wenn du das machst: "Hey jetzt sind es keine 100 mehr sondern nur noch weniger, ich hab zwar null plan wieviele aber das musst du rausfinden, schreib mir das in meine DataTable und mach so weiter"
    Dann macht er (wer immer "er" ist):
    "Hey jetzt sind es keine 100 mehr sondern nur noch weniger, ich hab zwar null plan wieviele aber das musst du rausfinden, schreib mir das in meine DataTable und mach so weiter"

    Er macht dann nicht:
    "schreibt er alles einzeln."

    Wenn er macht:
    "schreibt alles einzeln."
    dann macht er nicht: "Hey jetzt sind es keine 100 mehr sondern nur noch weniger, ich hab zwar null plan wieviele aber das musst du rausfinden, schreib mir das in meine DataTable und mach so weiter"
    sondern
    er schreibt alles einzeln.

    Wie gesagt: Schreibe deinen Code so, dass er
    "Hey jetzt sind es keine 100 mehr sondern nur noch weniger, ich hab zwar null plan wieviele aber das musst du rausfinden, schreib mir das in meine DataTable und mach so weiter"
    macht, und nichts anderes.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()