Announcement

Collapse
No announcement yet.

Abgleich großer Datenmengen MS-SQLServer

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Abgleich großer Datenmengen MS-SQLServer

    Ich habe eine manuelle Abgleichfunktion von Tabellen geschrieben, welche bei größeren Datenmengen furchtbar lange braucht. Ich weiss momentan nicht genau wo ich den Hebel ansetzen soll, um die Geschwindigkeit erträglich zu machen.

    Den Abgleich habe ich folgendermassen programmiert:

    von der Hauptdatenbank wird eine Tabelle mittels des BetterADODatasets geöffnet. Das offene Recordset speichere ich dann als XML und packe das ganze als ZIP. Die ZIP-Datei wird dann auf den Rechner der Ziel-Datenbank übertragen (FTP). Das Abgleich-Programm dort entpacht die Datei und lädt das XML-File wieder in ein BetterADODataset.

    Dann beginnt der eigentliche Abgleich. Da sich die Struktur der Tabellen gelegentlich ändert und ich nicht immer den Abgleich nachziehen will verwende ich die Fields auflistung.

    Code:
    qAbgleichDatei.First;
    while not qAbgleichDatei.eof do
    begin
     loeschen:=qAbgleichDatei.fieldbyname('ArtikelNummer').isnull;
     if adoArtikel.locate('ArtikelNummer;ArtikelIndex',varArrayOf([qAbgleichDatei.fieldbyname('LArtikelNummer').asinteger,qAbgleichDatei.fieldbyname('LArtikelIndex').asinteger]),[]) then
      begin
       if loeschen then
        begin
         adoArtikel.edit;
         adoArtikel.FieldByName('DELETED').asboolean:=true;
         adoArtikel.post;
        end
       else
        begin
         adoArtikel.edit;
         for i:= 0 to adoArtikel.FieldCount-1 do
          begin
           if adoArtikel.fieldList.fields[i].Value<>qAbgleichDatei.fieldbyname(adoArtikel.fieldList.fields[i].FieldName).Value then
            if adoArtikel.fieldList.fields[i].FieldName<>'Beschreibung' then
             adoArtikel.fieldList.fields[i].Value:=qAbgleichDatei.fieldbyname(adoArtikel.fieldList.fields[i].FieldName).Value
           end;
         adoArtikel.FieldByName('DELETED').asboolean:=false;
         adoArtikel.post;
        end;
      end
     else if not loeschen then
      begin
       adoArtikel.insert;
       for i:= 0 to adoArtikel.FieldCount-1 do
        begin
         if adoArtikel.fieldList.fields[i].FieldName<>'Beschreibung' then
          adoArtikel.fieldList.fields[i].Value:=qAbgleichDatei.fieldbyname(adoArtikel.fieldList.fields[i].FieldName).Value
        end;
       adoArtikel.FieldByName('DELETED').asboolean:=false;
       adoArtikel.post;
      end;
     qAbgleichDatei.next;
    end;
    die qAbgleichDatei ist das BetterADODateset in das die XML-Datei geladen wurde. adoArtikel ist das BetterADODataset, welches mit der Artikeltabelle des SQLServers verbunden ist (cmdTable, clUseClient, ctStatic). Die CurserLocation der Connection ist auf clUseClient gesetzt.

    Ein Abgleich von 40000 Datensätzen braucht weit über eine Stunde. Deis kann doch auf einem Core2 Rechner eigentlich nicht normal sein.

    Zur Sicherheit läuft der Abgleich in einer Transaktion ab (ist sicher auch relevant).

    Ich suche dringend eine Lösung!

    Gruß Markus

  • #2
    Ich habe jetzt die Funktion so umgeschrieben, dass sie mit Stored Procedurs arbeitet und immer nur einen Datnsatz aus der Zieltabelle liefert. Dadurch kann der SQLServer die Indizes sauber verwenden. Bei der Artikeltabelle (41.000 Datensätze mit 13 Spalten) dauert der Abgleich jetzt noc 22 Minuten, was ich immer noch als sehr lange empfinde. Hat jemand vieleicht sonst noch einen Optimierungsvorschlag?

    Comment


    • #3
      Versuch doch einmal das ADODataset als Datei abzuspeichern und auf dem Zielrechner wieder als Dataset einzubinden. Also ohne den Umweg über XML.
      Oder das transportierte Dataset erst auf dem Zielserver in eine Tabelle übergeben und dann den Abgleich mit SQL auf dem Server durchführen.

      Comment


      • #4
        Richtiger Gedanke, der Umweg über xml ist nicht notwendig.
        Allerdings gibt es einen einfacheren Weg der Dein System nicht 22 min werkeln läßt, sonder höchstens 4 sek benötigt. Dein Program arbeitet Datensatz für Datensatz ab. Mit einigen wenigen SQL-Befehlen hast Du 100% am Ende das gleiche Resultat. In einem Bruchteil der Zeit.
        Schiebe mal Deine Tabelle einfach in eine Accss-Datenbank. Öffne dann in Access die Datenbank und übe mal mit den Querys (Accss-Hilfe mit aufrufen) . Glaub mir in wenigen Minuten hast Du die richtige Abfrage gefunden. Und das ausfiltern von leeren oder doppelten Datensätzen usw ist ausführlich beschrieben und eine der leichtesten Aufgaben. Bei der Gelegenheit nutze dann auch die Exportfunktion von Access für den Rest.
        Gruß

        Comment

        Working...
        X