Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi 100.000 Datensätze in 22 Minuten - geht das noch schneller? (https://www.delphipraxis.net/159902-100-000-datensaetze-22-minuten-geht-das-noch-schneller.html)

mkinzler 19. Apr 2011 07:27

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Nein, dann verliert man den Vorteil des Prepare und bei jedem Insert muss in neuer Plan generiert werden.

jobo 19. Apr 2011 07:47

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Zitat:

Zitat von Blup (Beitrag 1095928)
Für optimale Geschwindig würde ich ein SQL-Script mit allen Insert und Update auf dem Client erzeugen und in einem Schritt durch den Server ausführen lassen.

Es fehlt auch die Logik, die feststellt, ob update oder insert.
Bei 100000 bedeutet das 200000 Operationen, bei denen nur die Hälfte erfolgreich ist und dort zu einem gewissen Anteil dann noch reihenweise Pk Verletzungen auftreten. Wahrscheinlich ist das nicht besonders schnell.

Blup 19. Apr 2011 14:23

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Jedes Statements nacheinander einzeln auszuführen ist erheblich langsamer, da die Ausführung jedes einzelnen Befehls erst einmal vom Server bestätigt werden muss, bevor der nächste gesendet wird. Das Script kann für jeden Datensatz die Procedur aufrufen, die von Fall zu Fall Update oder Insert ausführt.

Prepare bietet zwar bei komplizierten Abfagen Vorteile, dürfte hier aber keine große Rolle spielen.

IBExpert 19. Apr 2011 15:19

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Aufgrund mehrerer Anfragen, die ich in den letzten Tagen eh zu dem Thema bekommen hatte, habe ich gerade mal ein Tutorial zusammengestellt, das euch hoffentlich weiterhilft. Das ganze ist zwar in englischer Sprache, aber trotzdem recht simpel gehalten. Basis ist Firebird 2.5 und IBExpert, aber die IBExpert Teile lassen sich auch mit anderen Tools erledigen, wenn auch vielleicht weniger komfortabel. Für den Konvertierungsteil kann man auch problemlos Delphi einsetzen. Das Tutorial darf auch gerne auf anderen Foren veröffentlich werden, sofern die Inhalte unverändert sind, von üblichen Rechtsschreibfehlern mal abgesehen. In den nächsten Tagen wird das auch noch bei uns auf die Webseite eingearbeitet.

In dem Beispiel zeige ich Schritt für Schritt, wie man 100000 Datensätze aus einer csv Datei in 21 Sekunden importiert und verarbeitet, das sind eher die Werte, mit denen man rechnen sollte. 22 Minuten gehen da ja nahtlos in Lieferzeiten über, da wird dann schnell mal die Nacht zu kurz.

Kommentare gerne hier in der Delphipraxis oder auch direkt per email an mich: hklemt at ibexpert punkt com

http://www.ibexpert.com/download/Imp...portExport1.7z


p.s.: Ich hätte das auch hier hochgeladen, ging aber irgendwie nicht, trotz 4,2 MB. Nun denn, evtl. wird ja ein Moderator ein passendes Plätzchen finden

chaosben 19. Apr 2011 17:15

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
[Klugsch***]
Was der Holger da gemacht hat, beschreibt sich kurz so: Die CSV-Daten werden in das Firebird-External-Table-Format gewandelt und dann direkt in die DB als Tabelle "eingehangen".
Das geht wirklich wahnsinnig schnell und wir nutzen das schon einige Zeit im produktiven Umfeld.
[/Klugsch***]

Weil ich den Tip von ihm schon mal vor einiger Zeit bekommen habe, habe ich damals ne Delphi-Klasse dafür geschrieben. Wer also keinen IBExpert hat (mein Mitleid) kann diese Unit probieren.
Mit dieser Klasse kann man einen Datensatz generieren. Danach kann man ihn z.B. in einen Filestream schreiben. Dann noch Reset aufrufen und schon gehts von vorne los.
Bitte beachtet den Kommentar am Anfang der Datei. Wenn einer eine Lösung kennt, sagt bitte Bescheid.

//edit: So, nach ein wenig Suche&Finde sehe ich jetzt ein, das das External-Table-Format so lange gut ist, so lange man mit char-Felder arbeitet. Alles andere ist zu Prozessor/ODS-abhängig.

FredlFesl 19. Apr 2011 21:12

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Das sollte mit BULK INSERT unter SQL-Server auch sehr schnell gehen. Danach kann man mit ein paar Befehlen auf einmal einfügen bzw. überschreiben.

jobo 19. Apr 2011 23:16

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
100000 Datensätze mit Firebird
Ein schönes, ausführliches Beispiel, trotzdem ein paar Anmerkungen.
Ich hab das mit external table unter oracle ausprobiert. Gleiche Daten, gleiches Verfahren. Unterschied war nur, dass es mit rawdata.csv direkt, also delimited gelaufen ist.
Dabei bin ich auf ca 5 Minute Laufzeit via insert/update stored proc gekommen.
Aufgefallen ist mir, dass der Update Fall gar nicht eintritt, alles verschiedene IDs in rawdata.csv

Die Firebird Zeiten von 22 sec wundern mich aber schon etwas. Sind die wirklich mit der Stored Proc aus dem Tutorial gemessen?
Ein reines Insert- ohne SP- (was bei den Daten ja ok gewesen wäre, weil keine doppelten ID) dauert in meinem Test unter 2 Sekunden, was mir relativ plausibel erscheint, da die Zieltabelle aus dem Tutorial keinen Primärschlüssel / Index hat. Genau das wäre für mich auch der Grund für ein wesentlich länger dauerndes Insert/Update mittels satzweiser Stored Proc. 100000 mal ID suchen fürs Update ohne Index dauert halt. Wenn das bei Firebird wirklich so schnell geht, sollte ich mich vielleicht mehr damit beschäftigen! :)

Und was ich gar nicht verstehe:
Wenn man schon extra alles rüber schaufelt auf den Server -was ich ja gut finde- und direkt per SQL auf externe Daten zugreifen kann, wieso dann trotzdem satzweise importieren?
Wieso nicht eine Updateanweisung und eine Insertanweisung für alles? Oder geht so ein Update in Firebird nicht?

Sir Rufo 20. Apr 2011 00:06

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Hier mal das ganze mit MySQL:

Leere Tabelle
Zitat:

Zitat von MySQL
Code:
LOAD DATA INFILE 'C:/Users/...censored.../Desktop/rawdata.csv'
REPLACE
INTO TABLE tblimport
FIELDS
   TERMINATED BY ';'
IGNORE 1 LINES;
Affected rows: 100000
Time: 1.606ms

Und jetzt da drüber bügeln
Zitat:

Zitat von MySQL
Code:
LOAD DATA INFILE 'C:/Users/...censored.../Desktop/rawdata.csv'
REPLACE
INTO TABLE tblimport
FIELDS
   TERMINATED BY ';'
IGNORE 1 LINES;
Affected rows: 100000
Time: 2.417ms

Code:
CREATE TABLE `tblimport` (
  `ID` int(11) NOT NULL,
  `CATEGORY_ID` int(11) NOT NULL,
  `TITLE` varchar(100) DEFAULT NULL,
  `ACTOR` varchar(100) DEFAULT NULL,
  `PRICE` decimal(10,2) NOT NULL,
  `SPECIAL` int(11) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

mkinzler 20. Apr 2011 05:33

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Zitat:

Wieso nicht eine Updateanweisung und eine Insertanweisung für alles? Oder geht so ein Update in Firebird nicht?
FireBird unterstützt sowohl MERGE wie update or insert

jobo 20. Apr 2011 06:31

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Zitat:

by mkinzler
[Zitat]
Zitat:

by jobo
Wieso nicht eine Updateanweisung und eine Insertanweisung für alles? Oder geht so ein Update in Firebird nicht?
FireBird unterstützt sowohl MERGE wie update or insert
Hab ich mal wieder zu undeutlich ausgedrückt. Es geht mir nicht um den Unterschied zwischen einer Merge und einer Insert oder Update Anweisung. Es geht mir um das Verfahren in der SP aus dem Tutorial. Hier sind es nicht eine, sondern hundertausende solcher Anweisungen. Daher wundert mich die Angabe von 22 sec.

Wie gesagt, Insert hat bei mir unter 2 sec gedauert, update ca 0 sec, es gab ja keine. Merge habe ich nicht probiert.


Code:
for
    select ID, CATEGORY_ID, TITLE, ACTOR, PRICE, SPECIAL
    from IMPORT_PRODUCT
    into :ID, :CATEGORY_ID, :TITLE, :ACTOR, :PRICE, :SPECIAL
  do
  begin
    --is this record already there? 
    select count(*) from product where product.id=:id into :cnt;
    if (cnt=0) then
    begin
      --no, so do an insert
      insert into PRODUCT (ID, CATEGORY_ID, TITLE, ACTOR, PRICE, SPECIAL)
      values (:ID, :CATEGORY_ID, :TITLE, :ACTOR, :PRICE, :SPECIAL);
    end
    else
    begin
      --yes, so update the record
      update PRODUCT
      set CATEGORY_ID = :CATEGORY_ID,
          TITLE = :TITLE,
          ACTOR = :ACTOR,
          PRICE = :PRICE,
          SPECIAL = :SPECIAL
      where (ID = :ID);
    end
  end
  --thats all


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:06 Uhr.
Seite 2 von 4     12 34      

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