Delphi-PRAXiS

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)

Piro 18. Apr 2011 10:43

Datenbank: MS SQL 2005 • Version: Express • Zugriff über: ADO

100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Moin zusammen,

ich muss mit einer Stored Prozedure um die 100.000 Datensätze importieren. Später können das bis zu 500.000 Datensätze werden

Durch die Stored Prozedure "UPSERT" läuft der Prozess ca. 22 Minuten. Geht das noch schneller? Ich werde den Job Nachts ausführen. Dadurch ist die Zeit nicht so kritisch. Es wäre aber trotzdem gut zu wissen, ob ich schon alles optimiert habe.

In diesem Thread sieht man die abgespeckte Prozedure sowie den Quellcode.
http://www.delphipraxis.net/159900-s...tgestellt.html

Danke im Voraus für Verbesserungen und Ideen.
Sven

mkinzler 18. Apr 2011 10:59

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Ich würde alle oder zumindest mehrere Inserts innerhalb einer Transktion ausführen und nicht jeden insert in einen
MSSQL sollte zudem MERGE kennen

borwin 18. Apr 2011 11:26

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Wie sieht die Zieltabelle aus? Werden die Werte auf mehrer Tabellen verteilt?
Gibt es noch Trigger zu der Tabelle? Viewiel Indexe sind in der Tabelle?
Wie sehen die Daten aus? Welches Format haben die Importdaten?
Erfolgt der Import über einen Client?

Fragen die für eine Bewertung notwendig sind.

Gruß Borwin

Piro 18. Apr 2011 12:07

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Der Import der Daten erfolgt von einem Client (lässt sich nicht ändern). Die Daten kommen aus einer Textdatei (Semikolon getrennt).
Es wird nur eine SQL Tabelle verwendet, die nur einen Primärschlüssel besitzt.
Code:
...
CREATE TABLE [dbo].[mat_beweg](
   [id] [int] IDENTITY(1,1) NOT NULL,
   [snr] [nvarchar](9) NOT NULL,
   [b_ftag] [nvarchar](4) NOT NULL,
   [b_datum] [nvarchar](8) NOT NULL,
   [b_art] [nvarchar](2) NULL,
   [b_folge] [nvarchar](3) NULL,
   [ktr] [nvarchar](9) NULL,
   [znr] [nvarchar](3) NULL,
   [sinr] [nvarchar](7) NULL,
   [kst] [nvarchar](4) NULL,
   [k_art] [nvarchar](2) NULL,
   [umbnr] [nvarchar](5) NULL,
   [kz_es] [nvarchar](1) NULL,
   [bestand] [nvarchar](12) NULL,
   [menge] [nvarchar](12) NULL,
   [menge_storno] [nvarchar](12) NULL,
   [wemnr] [nvarchar](6) NULL,
   [bnr] [nvarchar](9) NULL,
   [lnr] [nvarchar](11) NULL,
   [preise] [nvarchar](2) NULL,
   [bpreis] [nvarchar](10) NULL,
   [preisart] [nvarchar](1) NULL,
   [dpreis] [nvarchar](10) NULL,
   [bwert] [nvarchar](11) NULL,
   [buch_datum] [nvarchar](8) NULL,
   [buch_grund] [nvarchar](20) NULL,
   [buch_user] [nvarchar](8) NULL,
   [zchnr] [nvarchar](38) NULL,
   [benennung] [nvarchar](36) NULL,
   [lieferant] [nvarchar](18) NULL,
   [lastupdate] [datetime] NOT NULL,
 CONSTRAINT [PK_mat_beweg] PRIMARY KEY CLUSTERED
(
   [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Stored Procedure "UPSERT"
Code:
/****** Objekt: StoredProcedure [dbo].[sp_upsert]   Skriptdatum: 04/18/2011 12:58:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_upsert]

   -- Add the parameters for the stored procedure here
   @snr nvarchar(9),
   @b_ftag nvarchar(4),
   @b_datum nvarchar(8),
        ...,
   @lastupdate datetime
AS
SET transaction isolation level SERIALIZABLE
SET NOCOUNT ON
BEGIN TRANSACTION Upsert
   
   update mat_beweg set snr = @snr,
                         b_ftag = @b_ftag,
                         b_datum = @b_datum,
                         ...
         lastupdate = @lastupdate
               where snr = @snr

   if @@rowcount = 0 and @@error=0
   begin
      insert into mat_beweg (snr, b_ftag, b_datum, ..., lastupdate)
                    values (@snr, @b_ftag, @b_datum, ..., @lastupdate)
   end
COMMIT TRANSACTION Upsert
Aufruf aus dem Program
Delphi-Quellcode:
...
with sp_upsert do
begin
  ProcedureName := 'sp_upsert';

  // Parameter-Liste aktualisieren
  Parameters.Refresh;

  Prepared := True;

  for i:=0 to 100000 do // symbolisch für die Datensätze
  begin
    Parameters.ParamValues['@snr']       := IntToStr(i);
    Parameters.ParamValues['@b_ftag']    := '6272';
    Parameters.ParamValues['@b_datum']   := '20110418';
    Parameters.ParamValues['@lastupdate'] := Now;
    ...
    ExecProc;
  end;

  Prepared := False;
end;
Das ganze ist nur ein einfacher Import (INSERT oder UPDATE). Ich hoffe die Infos sind ausreichend. Ein Merge funktioniert nicht, da ich SQL Server 2005 Express habe und die Funktion erst ab 2008 existiert.

Sir Rufo 18. Apr 2011 12:18

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
leg mal auf
Code:
snr
einen (Unique-) Index, dann geht das auch schneller ;)

taveuni 18. Apr 2011 12:23

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

Ich bin mir nicht sicher ob eine mehrfach aufgerufene SP für einen einfachen INSERT überhaupt
einen Performance Vorteil bringt.

Bezüglich des fehlenden MERGE:
Es gibt die Möglichkeit mit UNION ALL

Delphi-Quellcode:
INSERT INTO MyTable (FirstCol, SecondCol)
SELECT 'First' ,1
UNION ALL
SELECT 'Second' ,2
UNION ALL
SELECT 'Third' ,3
UNION ALL
SELECT 'Fourth' ,4
UNION ALL
SELECT 'Fifth' ,5
Die SELECTS kannst Du im Loop setzen.

Sir Rufo 18. Apr 2011 12:34

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

Zitat von taveuni (Beitrag 1095814)
Hallo,

Ich bin mir nicht sicher ob eine mehrfach aufgerufene SP für einen einfachen INSERT überhaupt
einen Performance Vorteil bringt.

Doch, dafür wird die Anweisung ja Prepared

Zitat:

Zitat von taveuni (Beitrag 1095814)
Bezüglich des fehlenden MERGE:
Es gibt die Möglichkeit mit UNION ALL

Delphi-Quellcode:
INSERT INTO MyTable (FirstCol, SecondCol)
SELECT 'First' ,1
UNION ALL
SELECT 'Second' ,2
UNION ALL
SELECT 'Third' ,3
UNION ALL
SELECT 'Fourth' ,4
UNION ALL
SELECT 'Fifth' ,5
Die SELECTS kannst Du im Loop setzen.

Nur, dass dann keine Parameter gehen

borwin 18. Apr 2011 12:58

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Mit dem SQL-Server habe ich zwar nicht viel am Hut.
Ich würde noch folgendes überlegen. Das gesamte Textfile der Procedure übergeben und dann in der SP
über einen Loop das Insert ausführen. Ich denke das bring bestimmt was.
Das Ergebnis würde mich schon interessieren. Sollte auch nicht so schwerr sein.


Gruß Borwin

jobo 19. Apr 2011 06:53

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Ich würde in jedem Fall das commit weglassen, so etwas gehört m.E. nicht an eine solche Stelle.
(Nicht nur wg. Performance- du hast dann nicht nur 100000 Datensätze, sondern eben auch 100000 commits, mit denen Du nichts gewinnst, es bedeutet auch Totalverlust der Transaktionskontrolle)

Wenn möglich/ nötig würde ich die Datei auf den Server laden und von dort weiterverarbeiten. Da ich nicht weiß, ob ms sql beim Zugriff auf externe Daten in diesem Fall auch mit Where Clause brauchbar arbeitet, empfiehlt sich evtl. eine separate Interface Tabelle, die nur die CSV Daten aufnimmt. Die kann mit externen Tools wie BCP(?) oder mit Bulk Insert from File befüllt werden. Im 2. Schritt dann Insert/Update, aber nicht satzweise, bitte.

Blup 19. Apr 2011 07:23

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
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.

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

mkinzler 20. Apr 2011 06:37

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Und du mich:
Es gibt in FireBird update or insert als ein erweitertes Insert-Statement, welches bei Bedraf ein Update macht:

SQL-Code:
update or insert into PRODUCT (ID, CATEGORY_ID, TITLE, ACTOR, PRICE, SPECIAL)
      values (:ID, :CATEGORY_ID, :TITLE, :ACTOR, :PRICE, :SPECIAL) matching (id);

jobo 20. Apr 2011 06:53

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Nein :) Das hab ich schon verstanden, aber wohl auch zu undeutlich gesagt. Mir ist schon aufgefallen, dass Du Or und nicht oder geschrieben hast, also dass Du die Anweisung meinst.

Das ändert aber auch nichts daran, dass es dem TE wahrscheinlich nicht weiterhilft. Während wir hier mit verschiedenen RDBMS basteln, steht diese schräge Sache mit dem satzweisen Verfahren im Raum, ein wie ich finde prinzipiell falsches.
Aber vielleicht sollte der TE sowieso mal was dazu sagen.

FredlFesl 20. Apr 2011 08:17

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Will der Fragesteller wirkklich seine Stored Procedure verwenden? Ist doch blöd.

So gehts in ein paar Sekunden.

Code:
-- CSV-Datei importieren
BULK INSERT #Temp
FROM 'c:\file.csv'
WITH ( 
     FIELDTERMINATOR = ';',
     ROWTERMINATOR = '\n'
     )
-- Index auf Primärschlüssel setzen (kann die Sache noch ordentlich beschleunigen)
CREATE INDEX Temporaer ON #Temp (Key)

-- Existierende Daten ersetzen
UPDATE ZielTabelle SET Feld = #Temp.Inhalt,
       NochEinFeld = #Temp.NochEinInhalt
 FROM Temp WHERE #Temp.Key = ZielTabelle.Key

-- Neue Daten anhängen
INSERT INTO ZielTabelle
  (Feld1, NochEinFeld)
SELECT Inhalt, NochEinInhalt
  FROM #Temp LEFT JOIN
       ZielTabelle ON #Temp.Key = ZielTabelle.Key
 WHERE ZielTabelle.Key IS NULL

IBExpert 20. Apr 2011 09:18

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Ich hab in meinem Beispiel explizit eine Stored Procedure verwendet, weil ein Datenimport in 90 % der Fälle leider nicht nur mal eben mit "update or insert" oder merge über Primary Key ausreicht, auch wenn meine Demo Prozedur nicht mehr macht. Daher läuft bei mir der Import immer zweistufig, erst mal die Daten rein in die DB, dann in der DB via SP verteilen. Und das hat sich in erster Linie deshalb bewährt, weil das mit SP eben so schnell ist.

Wenn du die DB1 Demo DB auf deinem Rechner hast, dann starte einfach mal die Prozedur initall mit dem Parameter 10000. Damit werden aus den TMP_* Tabellen Demodaten generiert. Wenn man jetzt mal die TMP_* Tabellen als Import und die anderen Tabellen als finale Daten betrachtet, dann sieht man, was im Rahmen einer SP an speed möglich ist, zumindest bei Firebird, ich weiß von anderen Plattformen, wo SP weniger verbreitet sind, weil meistens auch nicht so schnell.

konkrete Daten und Performanceanalyse aus Firebird/IBExpert:

Code:
BEFEHL

execute procedure INITALL(10000);

Query
------------------------------------------------


Plan
------------------------------------------------


Query Time
------------------------------------------------
Prepare      : 0,00 ms
Execute      : 8.612,00 ms
Avg fetch time: 0,00 ms

Memory
------------------------------------------------
Current: 337.372.048
Max   : 337.833.024
Buffers: 20.000

Operations
------------------------------------------------
Read  : 114
Writes : 570
Fetches: 3.570.581


Enchanced Info:
+--------------------------+-----------+-----------+-------------+---------+---------+---------+
|        Table Name       |  Records |  Indexed | Non-Indexed | Updates | Deletes | Inserts |
|                          |   Total  |   reads  |    reads   |         |         |         |
+--------------------------+-----------+-----------+-------------+---------+---------+---------+
|                  CUSTOMER|         0 |         2 |           0 |       0 |       0 |   10000 |
|                 INVENTORY|         0 |     70476 |           0 |   35238 |       0 |   10000 |
|                 ORDERLINE|         0 |         0 |           0 |       0 |       0 |   35238 |
|                    ORDERS|         0 |     45238 |           0 |   10000 |       0 |   10000 |
|                   PRODUCT|         0 |     35240 |           0 |       0 |       0 |   10000 |
|                   TMP_ADR|         0 |     10000 |           0 |       0 |       0 |       0 |
|                  TMP_CITY|         0 |      9999 |           0 |       0 |       0 |       0 |
|                    TMP_FN|         0 |      9996 |           0 |       0 |       0 |       0 |
|                   TMP_FN2|         0 |     19959 |           0 |       0 |       0 |       0 |
|                    TMP_LN|         0 |      9994 |           0 |       0 |       0 |       0 |
|                   TMP_LN2|         0 |     19962 |           0 |       0 |       0 |       0 |
|                 TMP_STATE|         0 |      9895 |           0 |       0 |       0 |       0 |
|             TMP_TITLEWORD|         0 |     29987 |           0 |       0 |       0 |       0 |
+--------------------------+-----------+-----------+-------------+---------+---------+---------+
oder mit anderen Worten:
Während der Ausführung der Prozedur wurden 391224 individuelle Insert/Update/Delete Statements
ausgeführt und gedauert hat das 8,6 Sekunden. Das die zigtausend Aufrufe von Zufallszahlen in
der Prozedur auch noch Zeit kosten ist klar, wenn man sich der Code in der Prozedur INITALL
ansieht.

Meßergebnis sind auf dem Wege aber über 45000 Operationen pro Sekunde, die man im Rahmen einer
Stored Procedure problemlos erreichen kann. Damit lassen sich auch richtig große Datenmengen
in vertretbaren Zeiten verarbeiten (Ich weiß von einem Kunden im Iran, der eine Firebird
DB mit 15TB betreibt, normal sind aber meistens Datenbankgrößen zwischen 100MB und 1TB).

Ich wollte nur noch mal deutlich machen, warum ich im Tutorial den vermeindlichen Umweg über
die SP gegangen bin, wenn man alles mit einer Zeile Code erledigen könnte, dann hätten die
meisten von uns keinen Job.

So sähe der gleich Befehl in Firebird und einigen anderen DBs übrigens als SQL ohne SP aus
Code:
merge into product p
using import_product ip
on p.id = ip.id
when matched then
update set CATEGORY_ID = IP.CATEGORY_ID,
           TITLE = IP.TITLE,
           ACTOR = IP.ACTOR,
           PRICE = IP.PRICE,
           SPECIAL = IP.SPECIAL
when not matched then
        insert (ID, CATEGORY_ID, TITLE, ACTOR, PRICE, SPECIAL)
        values (IP.ID, IP.CATEGORY_ID, IP.TITLE, IP.ACTOR, IP.PRICE, IP.SPECIAL)

FredlFesl 20. Apr 2011 17:46

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
IBExpert, toll das es mit Firebird geht (wäre ja auch noch schöner).
Der Fragesteller hat aber MSSQL, soweit ich mich erinnere.

IBExpert 20. Apr 2011 19:47

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
ja, das ist mir auch klar, aber hier und da findet man in der eigenen Plattform durchaus vergleichbare Techniken.

Und ganz ehrlich, wenn ein Import von 100000 Sätzen 22 Minuten dauert kann man auch mal über die eigene Plattform
nachdenken, wahlweise in Bezug auf die eigenen Kenntnisse oder eben die Technischen Möglichkeiten der jeweiligen
Software.

Das MSSQL das unbestritten schneller können sollte ist ja eh klar, aber Foren wie die Delphipraxis zeichnen
sich ja lobenswerterweise nicht durch uneingeschränkte Microsoftgläubigkeit aus.

FredlFesl 20. Apr 2011 22:18

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

Zitat von IBExpert (Beitrag 1096277)
Das MSSQL das unbestritten schneller können sollte ist ja eh klar, aber Foren wie die Delphipraxis zeichnen
sich ja lobenswerterweise nicht durch uneingeschränkte Microsoftgläubigkeit aus.

Behauptet keiner, und Niemand hat bisher von Microsoftgläubigkeit geredet. Ich dachte nur, man sollte beim Thema und damit der Plattform bleiben, das ist alles.

Piro 21. Apr 2011 21:29

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Schönen guten Abend,

das ist ja mal ne Menge an Antworten.

Ich bin an MSSQL gebunden und möchte auch nicht wechseln. Ist halt strategisch vorgegeben.

Ich werde es mal mit dem Bulk Insert oder dem CSV Import versuchen.

@FredlFesl: Wie muss ich denn die einzelnen Anweisungen setzen?
Den Import kann ich mit der TADOCommand ausführen. Danach ist mir aber nicht klar, wie es weiter geht. Wenn ich jetzt erst eine Abfrage machen soll, wo der Datensatz vorhanden ist und anhand des Ergebnisses ein INSERT oder UPDATE durchführe, habe ich doch wieder Geschwindigkeitseinbußen. Deshalb habe ich halt, die Stored Procedure UPSERT verwendet.

Ich versuche mal den Bulk INSERT

Bummi 21. Apr 2011 23:18

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
die Methode von FredlFesl dürfte für Dich die schnellste und einfachste sein.
Der unterschied ist daß Du nach dem Bulk insert, welcher schnell geht mit Mengen arbeitest und nicht mehr mit einzelnen Sätzen, mit den passenden Indizes würde ich darauf tippen dass Dein Import/Update so in ein paar Sekunden rein läuft.

EDIT:

Du muss die Struktur für #TEMP bereitstellen, also per Create Table oder per
Code:
Select x,y,z
into #temp
From VorlageOderZiel
Where 1=0
zudem muss sich die Importdatei auf dem Server befinden, oder vom Server aus zugreifbar sein und Du könntest Probleme mit Umlauten bekommen....

Piro 21. Apr 2011 23:25

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
So, ich habe es jetzt mit dem BULK INSERT gemacht.

Da ich die Daten jeden Tag neu brauche. Mache ich erst ein Trunc auf die Table und dann ein BULK INSERT.

Ich habe eben ca. 1Mio. Datensätze importiert. Es hat knapp 1Minute gedauert.

Vielen Dank an alle.

FredlFesl 22. Apr 2011 07:51

AW: 100.000 Datensätze in 22 Minuten - geht das noch schneller?
 
Falls Du einen Index verwendest, oder die "1 Minute"-Marke knacken willst, kannst Du hier nachlesen, ob und wie das geht.
http://technet.microsoft.com/de-de/l...,SQL.100).aspx


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:14 Uhr.

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