Delphi-PRAXiS
Seite 3 von 5     123 45      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Insert into (https://www.delphipraxis.net/204167-insert-into.html)

Walter Landwehr 31. Aug 2020 11:01

AW: Insert into
 
Ich muss das Thema nochmals aufgreifen. Ich habe jetzt eine StoredProc gemacht leider mit den gleichen Erfolg. Um 10 Datensätze in die Datei zu schreiben werden 72 Sec. benötigt. Viel zu Lange. Wer kann mir natürlich gegen Entgeld weiterhelfen.

jziersch 31. Aug 2020 15:01

AW: Insert into
 
2 Ideen:

- Verwendest Du Start-/EndTransactions um Deine Schleife
- Lösch doch mal die Indices

haentschman 31. Aug 2020 15:10

AW: Insert into
 
Zitat:

Lösch doch mal die Indices
...wenn ich mich recht erinnere, dann waren bei Firebird zusammengesetzte Indizies eher kontraproduktiv.:gruebel:
Zitat:

Um 10 Datensätze in die Datei zu schreiben werden 72 Sec. benötigt
...daß heißt, für ein insert into 7,2 Sekunden? :shock:

Vieleicht ist es auch sowas wie mit ADO? ...aber eher unwahrscheinlich.
https://www.delphipraxis.net/192080-ado-langsam.html

jobo 31. Aug 2020 17:39

AW: Insert into
 
Wie hast Du denn die Procudure aufgebaut?
Die Procedure hat den Sinn, die Trigger (weitgehend) zu ersetzen, also eine dedizierte Insert Proc, die alles regelt, alles bis auf meinetwegen Erzeugung der ID des PK. Jedenfalls würde die Proc naturgemäß eine Aufgabe erledigen, hier insert. Deine Trigger bedienen aber mehrere Aufgaben...
Wie ist das umgesetzt?

Hab mir die Trigger noch mal angeschaut. Diesmal sind mir die POSITION Angaben aufgefallen, die mehrmals mehrdeutig sind. Wie sich fb verhält, wenn POSITION mehrdeutig ist, aber für unterschiedliche Mutation Types, weiß ich nicht. Das bedeutet aber vielleicht, das Feuern der Trigger ist in der Reihenfolge mehr oder weniger undefiniert, also zufällig. In der Praxis wäre das ein möglicher Grenzwertfall. Zufällig bedeutet ja nicht, dass es jedesmal anders läuft, bunt durcheinander (und Du schon nach wenigen Inserts über falsche Ergebnisse gestolpert wärst, weil die innere Abhängigkeit der Insert Logik verletzt wird), sondern immer nach dem gleichen, undefinierten Schema (das sich durch interne Algorithmen ergibt) bis ein Kipppunkt (wegen Laufzeit, ..) erreicht ist und die Trigger in anderer Reihenfolge zünden.

Ggf. könntest du in einem funktionierenden (kleinen) System die Trigger so erweitern, dass sie alle ihren Namen und einen fortlaufenden Sequenzwert in eine separate Tabelle eintragen. Diese (funktionierende) Reihenfolge dann über die POSITION Angabe richtig festnageln und auf das große System übertragen (oder wenigstens vergleichen, wie es sich im großen System verhält).
Vielleicht kann man das aber auch einfacher per Trace API feststellen.

Oder mal die SP zeigen (mit den übrig gebliebenen Triggern)

Den Hinweis zur (expliziten) Start/End Transaction finde ich auch wichtig, bei einem einzelnen Insert oder bei einem Einzelnen Aufruf einer Insert Proc ist das nicht notwendig (und meistens kontraproduktiv), da es implizit DB-seitig erfolgt.

Walter Landwehr 1. Sep 2020 11:01

AW: Insert into
 
Habe mal alle Indexe gelöscht.

Hier mal die Procedure:
Delphi-Quellcode:
SET TERM ^ ;

create or alter procedure TBL_RECHNUNGSPOSITIONEN_INS (
    RECHNUNGSPOSITIONENNR type of column TBL_RECHNUNGSPOSITIONEN.RECHNUNGSPOSITIONENNR,
    RECHNUNGNR type of column TBL_RECHNUNGSPOSITIONEN.RECHNUNGNR,
    PATIENTENNUMMER type of column TBL_RECHNUNGSPOSITIONEN.PATIENTENNUMMER,
    BEHANDLUNGSDATUM type of column TBL_RECHNUNGSPOSITIONEN.BEHANDLUNGSDATUM,
    MITARBEITERNUMMER type of column TBL_RECHNUNGSPOSITIONEN.MITARBEITERNUMMER,
    BEHANDLER type of column TBL_RECHNUNGSPOSITIONEN.BEHANDLER,
    GEBUEHNR type of column TBL_RECHNUNGSPOSITIONEN.GEBUEHNR,
    CODENR type of column TBL_RECHNUNGSPOSITIONEN.CODENR,
    SUCHWORT type of column TBL_RECHNUNGSPOSITIONEN.SUCHWORT,
    TEXT type of column TBL_RECHNUNGSPOSITIONEN.TEXT,
    GOAENR type of column TBL_RECHNUNGSPOSITIONEN.GOAENR,
    MENGE type of column TBL_RECHNUNGSPOSITIONEN.MENGE,
    FAKTOR type of column TBL_RECHNUNGSPOSITIONEN.FAKTOR,
    EINZELPREIS type of column TBL_RECHNUNGSPOSITIONEN.EINZELPREIS,
    STEUERCODE type of column TBL_RECHNUNGSPOSITIONEN.STEUERCODE,
    STEUERBETRAG type of column TBL_RECHNUNGSPOSITIONEN.STEUERBETRAG,
    STEUERSATZ type of column TBL_RECHNUNGSPOSITIONEN.STEUERSATZ,
    GESAMTBETRAG type of column TBL_RECHNUNGSPOSITIONEN.GESAMTBETRAG,
    ANLAGE type of column TBL_RECHNUNGSPOSITIONEN.ANLAGE,
    ANLAGEBENUTZER type of column TBL_RECHNUNGSPOSITIONEN.ANLAGEBENUTZER,
    AENDERUNG type of column TBL_RECHNUNGSPOSITIONEN.AENDERUNG,
    AENDERUNGBENUTZER type of column TBL_RECHNUNGSPOSITIONEN.AENDERUNGBENUTZER,
    MERKER type of column TBL_RECHNUNGSPOSITIONEN.MERKER,
    TIERENR type of column TBL_RECHNUNGSPOSITIONEN.TIERENR,
    KATEGORIE type of column TBL_RECHNUNGSPOSITIONEN.KATEGORIE,
    SPLITTING type of column TBL_RECHNUNGSPOSITIONEN.SPLITTING,
    MEDIKAMENT type of column TBL_RECHNUNGSPOSITIONEN.MEDIKAMENT,
    GEBUEHRENNR type of column TBL_RECHNUNGSPOSITIONEN.GEBUEHRENNR,
    TYP type of column TBL_RECHNUNGSPOSITIONEN.TYP,
    LKZ type of column TBL_RECHNUNGSPOSITIONEN.LKZ,
    BEHANDLERNUMMER type of column TBL_RECHNUNGSPOSITIONEN.BEHANDLERNUMMER,
    GEHOERTZU type of column TBL_RECHNUNGSPOSITIONEN.GEHOERTZU,
    TARIF type of column TBL_RECHNUNGSPOSITIONEN.TARIF,
    EINZELPREISBRUTTO type of column TBL_RECHNUNGSPOSITIONEN.EINZELPREISBRUTTO)
as
begin
  insert into tbl_rechnungspositionen (
    rechnungspositionennr,
    rechnungnr,
    patientennummer,
    behandlungsdatum,
    mitarbeiternummer,
    behandler,
    gebuehnr,
    codenr,
    suchwort,
    text,
    goaenr,
    menge,
    faktor,
    einzelpreis,
    steuercode,
    steuerbetrag,
    steuersatz,
    gesamtbetrag,
    anlage,
    anlagebenutzer,
    aenderung,
    aenderungbenutzer,
    merker,
    tierenr,
    kategorie,
    splitting,
    medikament,
    gebuehrennr,
    typ,
    lkz,
    behandlernummer,
    gehoertzu,
    tarif,
    einzelpreisbrutto)
  values (
    :rechnungspositionennr,
    :rechnungnr,
    :patientennummer,
    :behandlungsdatum,
    :mitarbeiternummer,
    :behandler,
    :gebuehnr,
    :codenr,
    :suchwort,
    :text,
    :goaenr,
    :menge,
    :faktor,
    :einzelpreis,
    :steuercode,
    :steuerbetrag,
    :steuersatz,
    :gesamtbetrag,
    :anlage,
    :anlagebenutzer,
    :aenderung,
    :aenderungbenutzer,
    :merker,
    :tierenr,
    :kategorie,
    :splitting,
    :medikament,
    :gebuehrennr,
    :typ,
    :lkz,
    :behandlernummer,
    :gehoertzu,
    :tarif,
    :einzelpreisbrutto);
end^

SET TERM ; ^

/* Folgende GRANT Anweisungen werden automatisch generiert */

GRANT INSERT ON TBL_RECHNUNGSPOSITIONEN TO PROCEDURE TBL_RECHNUNGSPOSITIONEN_INS;

/* Aktuelle Priviligien auf dieser Prozedur */

GRANT EXECUTE ON PROCEDURE TBL_RECHNUNGSPOSITIONEN_INS TO "PUBLIC";
GRANT EXECUTE ON PROCEDURE TBL_RECHNUNGSPOSITIONEN_INS TO SYSDBA;
Ich denke das Liegt an den Triggern. kann mn alles in eine Proc packen inklusive der Schleife?

jobo 1. Sep 2020 11:28

AW: Insert into
 
So nützt die Proc nichts.
Du musst den gesamten Triggercode für das Insert dort aus den Triggern ausbauen (ggf ganze Trigger weglassen) und in die Proc packen.
Die Schleife gehört nicht in die Proc rein.

Die Proc soll das Insert selbst ausführen und alle nachgelagerten Updates und Summenbildung.

Triggercode für update, delete muss erhalten bleiben, solange das nicht ähnlich umgebaut wird.

Also alle betroffenen Trigger disablen und Code "umschichten", in Anführungszeichen, weil es sicher keine 100% Copy/Paste Aktion ist. Mindestens fallen Fallunterscheidungen für den Mutation Typ weg, es geht in der Proc ja nur noch ums Insert.
Außerdem muss Before / After entsprechend in den Flow der Proc einfließen.

Mit disabled Triggern solange die Proc entwickeln/testen, bis ein sauberes insert per Proc gelingt.
Diese Proc kann dann natürlich wie zuvor das Insert in Schleife aufgerufen werden.
Der Test der Proc, also Aufruf und Prüfung des Ergebnis am besten direkt in der SQL Console bis alles stimmt.

Walter Landwehr 1. Sep 2020 12:22

AW: Insert into
 
OK habe ich mir schon gedacht, werde das ganz umbauen und auf die trigger verzichten.

TigerLilly 2. Sep 2020 08:54

AW: Insert into
 
Schau doch, was der Server wirklich macht! Stichwort Trace. Du rätst jetzt herum + weißt nicht, wo du hingreifen sollst.

1) Was macht die Hardware? Rödelt die Platte herum? Kocht der Prozessor?
2) Was macht die Datenbank? Werden triggers ohne Ende gefeuert? Was genau braucht wie lange?

Nur wenn du weißt, was das Problem ist, kannst du es verlässlich lösen + beim nächsten Mal vermeiden!

Delphi.Narium 2. Sep 2020 16:37

AW: Insert into
 
Bei allen SQLs, egal ob Select, Insert, Update, Delete mal den Ausführungsplan anschauen.

Bei Statements, die nur einen Satz "anpacken", sollte ein entsprechender Index genutzt werden. Fehlt der, wird jedesmal die gesamte Datenbank "durchgegraben" (Full Table Scan). Und sowas (schlimmstenfalls mehrfach) in einem Trigger pro Datensatz: Jo, das kann dann schonmal dauern, da wären die von Dir beobachteten Zeiten schon fast kurz zu nennen ;-)

Hat die Tabelle tbl_Artikel einen Index auf ArtikelNr?
Hat die Tabelle tbl_PatDiagnose einen Index auf (ReferenzTabelle, ReferenzNr)?
Hat die Tabelle TBL_PATDIAGNOSE einen Index auf (ReferenzTabelle, ReferenzNr, Dauerdiagnose)?
Hat die Tabelle TBL_PATIENT einen Index auf PATIENTENNUMMER?
Hat die Tabelle TBL_RECHNUNG einen Index auf rechnungNr?

Hat die Tabelle TBL_RECHNUNGSPOSITIONEN einen Index auf (RechnungNr, Steuercode)?
(Laut Createscript von oben nicht, aber pro Insert ein
SQL-Code:
Select sum(Steuerbetrag) from TBL_RECHNUNGSPOSITIONEN where RechnungNr = :RechnungNrInt and Steuercode = 1 Into :Steuer1;
Das schreit so nach 'nem Full Table Scan!!! Oder auch: Hilf mir, ich rödel mir hier 'nen Wolf.)

Das sind jetzt nur mal so "Indexideen". Was Du genau benötigst, was eher kontraproduktiv ist, muss Du wohl oder übel ausprobieren. Jedenfalls gibt es für alles, was ich da vorgeschlagen habe, entsprechende Selects, Updates, ... in den Triggern. Auch wenn die Trigger durch 'ne Prozedur ersetzt werden und sich eventuell die Geschäftslogik dadurch vereinfachen lässt: Solange die Datenbank für viele, einige oder alle Statements 'nen Full Table Scan pro Insert machen muss, wird es nicht wirklich schnell werden.

TigerLilly 3. Sep 2020 06:58

AW: Insert into
 
Das würde ich gern ergänzen: Beim Insert müssen Indices aktualisiert werden, dh da kosten sie eher Zeit. Bei einem Update und Delete helfen sie, den Satz schneller zu finden + bringen eher Zeit.

Aber die Dosis macht das Gift, viele und große und vielleicht sogar redundante Indices kosten uU mehr Zeit als sie bringen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:11 Uhr.
Seite 3 von 5     123 45      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz