Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Datensätze vergleiche (https://www.delphipraxis.net/96898-datensaetze-vergleiche.html)

Dumpfbacke 1. Aug 2007 12:51

Datenbank: Interbase • Version: 6.01 • Zugriff über: IBX

Datensätze vergleiche
 
Hallo,
ich hänge immernoch an meinem Problem mit den 800.000 Datensätze. Nun hänge ich an einer anderen Stellen, da nun die Wünsche geändert wurden. Ich beschreibe mal die Gegebenheiten und mein Problem. Villeicht könnt Ihr mir ja nochmals helfen.

Als Ergebnis sollte herrauskommen:
Welche sind neue Daten und bei welchen hat sicht etwas geändert.

Es liegen zwei CSV Dateien mit jewals fast 800.000 Datenstzäte vor. Diese beiden Dateien habe ich ich zwei Tabellen im Interbase geschrieben. (Kein Problem geht sehr zügig)

Die 1. Tabelle sind so aufgebaut

Feld1 VarChar(150) Character Set ISO8859_1
Feld2 VarChar(150) Character Set ISO8859_1
Fled3 VarChar(40) Character Set ISO8859_1
Feld4 VarChar(3) Character Set ISO8859_1
Feld5 VarChar(20) Character Set ISO8859_1
Fled6 VarChar(10) Character Set ISO8859_1

Die 2. Tabelle sieht genau so aus hat jedoch noch ein Feld für ein Datum

In der 1. Tabelle sind die alten Daten und in der 2. Tabelle sind die neuen Daten.

Nun wollte ich in alle Datensätze in der Tabelle2 das aktuelle Datum schreiben, wenn die Datensatz in der Tabelle1 vorhanden ist. Somit müßte der rest ohne Datum dann neu sein oder geändert worden.

Dazu habe ich es zuerst versucht mit einen Update

SQL-Code:
 Update Tabelle2
Set Datumsfeld = '01.08.07'
where Feld1 || Feld2 || Feld3 || Feld4 || Feld5 || Feld6 
in (Select Feld1 || Feld2 || Feld3 || Feld4 || Feld5 || Feld6  From Tabelle2)
Das ganze lief zwei Stunden und es hat sich nicht getan. Da habe ich es mal abgebrochen, da es villeicht noch Tage dauern kann bis das Ergebnis vorliegt.

Dann habe ich auf jedes Feld einen Index gesetzt. Einen Index über alle Felder geht ja leider nicht, da er ja zu "breit" ist. Leider

Das ganze mit den Abgleich kann auch genre 10 Stunden dauern nur das Ergebnis sollte stimmen. Also dacht ich mir mach es halt über ein Schleife. Ja mir ist bekannt es ist das schlechteste ist was ich machen kann.
Alle Datensätze der Tabelle 1 hole ich in eiene TIBQuery und mittels einer Schleife suche dann mittels einer TIBQuery den Datensatz in Tabelle2. Wenn das Ergebnis nicht Leer ist setzte ich das Datum. Wenmn ein Feld nicht übereinstimmt wurde etwas geändert. Das ganze geht auch, würde jedoch ca. 123 Stunden dauern und das ist mir etwas zu lange.

Kann mir jemand hier einen Tip geben wie ich es schneller hinbekommen werden. Man die Leute haben wünsche. Sage mir mal den Unterschied bei 800.000 Datensätzen. :wall: :gruebel:

Tanja

mkinzler 1. Aug 2007 13:03

Re: Datensätze vergleiche
 
Der Concat scheint sehr langsam zu sein. Versuchs mal mit dem ausführlichen Statement

DeddyH 1. Aug 2007 13:14

Re: Datensätze vergleiche
 
Ich würde es so versuchen (ungetestet):
SQL-Code:
UPDATE Tabelle2 B
SET B.Datumsfeld = '01.08.2007'
WHERE EXISTS(
  SELECT * FROM Tabelle1 A
  WHERE A.Feld1 = B.Feld1
  AND A.Feld2 = B.Feld2
  AND A.Feld3 = B.Feld3
  AND A.Feld4 = B.Feld4
  AND A.Feld5 = B.Feld5
  AND A.Feld6 = B.Feld6)

hoika 1. Aug 2007 13:20

Re: Datensätze vergleiche
 
Hallo,

SQL-Code:
Update Tabelle2
Set Datumsfeld = '01.08.07'
where Feld1 || Feld2 || Feld3 || Feld4 || Feld5 || Feld6
in (Select Feld1 || Feld2 || Feld3 || Feld4 || Feld5 || Feld6  From Tabelle2)
Hast du das falsch abgetippt,
es muss doch heissen
in ( XXXFrom Tabelle1)
statt Tabelle2


Nun zum Speed

Ich würde in beide Tabellen ein SumFeld Varchar(XXX) (Summe aller Felder)
eintragen, es per Update füllen
(Update Table1 Set SumFelds = Field1 || Field 2 || ...)

SQL-Code:
Update Tabelle2
Set Datumsfeld = '01.08.07'
where Tabelle2.SumFeld1 not exists in
(Select Tabelle1.SumFeld From Tabelle1
Das Exisst sollte das noch etwas schneller machen.


Heiko
PS: Die beiden SumFeld können danach ja wieder gelöscht werden.

marabu 1. Aug 2007 14:39

Re: Datensätze vergleiche
 
Hallo Tanja,

eine weitere Möglichkeit: Vor dem Laden der Dateien ein Feld mit dem Hash-Wert aller Feldinhalte hinzufügen - oder auch nach dem Laden über eine MD5 UDF, einen Index auf den Hash setzen und ein UPDATE mit dem bereits gezeigten Sub-Select.

Freundliche Grüße

Dumpfbacke 1. Aug 2007 17:14

Re: Datensätze vergleiche
 
Zitat:

Zitat von hoika
Hallo,


Hast du das falsch abgetippt,
es muss doch heissen
in ( XXXFrom Tabelle1)
statt Tabelle2

Oh ja da habe ich micht vertippelt.

Zitat:

Zitat von hoika
Nun zum Speed

Ich würde in beide Tabellen ein SumFeld Varchar(XXX) (Summe aller Felder)
eintragen, es per Update füllen
(Update Table1 Set SumFelds = Field1 || Field 2 || ...)

Das habe ich gemacht und es hat nur einige Minuten gedauert.

Zitat:

Zitat von hoika
SQL-Code:
Update Tabelle2
Set Datumsfeld = '01.08.07'
where Tabelle2.SumFeld1 not exists in
(Select Tabelle1.SumFeld From Tabelle1
Das Exisst sollte das noch etwas schneller machen.

Hier ist nun meine Problem. Ich habe es weiterhin nur in versucht und es dauert und dauert. Ich habe es dann abgebrochen. Das Problem hier ist mein Interbase 6 kann nicht not existis in

Tanja
PS: Die beiden SumFeld können danach ja wieder gelöscht werden.[/quote]

grenzgaenger 1. Aug 2007 17:24

Re: Datensätze vergleiche
 
hallo tanja,

sag mal, sind die datensätze sortiert? falls ja, brauchst du die tabellen nicht in eine datenbank zu schreiben, sondern nur die beiden tabellen lesen, durchschleifen und die unterschiede ausgeben... sollte programmmässig in ein paar sekunden durchgelaufen sein.

aber die tabellen müssen nach dem primärschlüssel sortiert sein. sonst musst du immer die ganze tabelle durchhangeln und das geht in die zeit...

grüsse
gg

alzaimar 1. Aug 2007 18:24

Re: Datensätze vergleiche
 
Hier bietet sich z.B. Beyond Compare an, ein wirklich gutes Tool für diesen Zweck.

hoika 1. Aug 2007 21:29

Re: Datensätze vergleiche
 
Hallo

argzz

where not exists (select bla)

es heisst nicht not exists in (select() sondern not exists (select()


Heiko

beha 1. Aug 2007 22:08

Re: Datensätze vergleiche
 
Hallo,

ich möchte nur noch anmerken, dass man mit der zu Beginn erwähnten Concat-Lösung eine Änderung an einem Datensatz evtl. nicht findet, obwohl diese stattgefunden hat. Beispiel:

alter Datensatz: Feld1=ABC Feld2=DEF ...
neuer Datensatz: Feld1=AB Feld2=CDEF ...

hier hat sich was geändert, aber die Änderung würde anhand eines Vergleichs von Feld1 || Feld2 nie festgestellt werden !

Also, falls so was in der Praxis vorkommen kann, kann ein Vergleich mittels || nicht das gewünschte Ergebnis liefern.

beha

alzaimar 2. Aug 2007 05:29

Re: Datensätze vergleiche
 
Na ja, dann packt man ein Trennzeichen zwischen die einzelnen Felder, das sonst im Text nicht vorkommt. Es ist sowieso performanter, einen Hash zu erzeugen, und diesen für einen Vergleich heranzuziehen.

Dumpfbacke 2. Aug 2007 05:53

Re: Datensätze vergleiche
 
Zitat:

Zitat von hoika
Hallo

argzz

where not exists (select bla)

es heisst nicht not exists in (select() sondern not exists (select()


Heiko

Hallo Heiko,
mein Interbase 6 kennt kein exists. Ich bekomme immer die Fehlermeldung

Dynamic SQL Error
SQL error code = -104
Token unknown - line 2, char 14
exists

Tanja

Dumpfbacke 2. Aug 2007 05:54

Re: Datensätze vergleiche
 
Zitat:

Zitat von grenzgaenger
hallo tanja,

sag mal, sind die datensätze sortiert? falls ja, brauchst du die tabellen nicht in eine datenbank zu schreiben, sondern nur die beiden tabellen lesen, durchschleifen und die unterschiede ausgeben... sollte programmmässig in ein paar sekunden durchgelaufen sein.

aber die tabellen müssen nach dem primärschlüssel sortiert sein. sonst musst du immer die ganze tabelle durchhangeln und das geht in die zeit...

grüsse
gg

Nei die Daten sind nicht sortiert und kann sich jedes mal ändern.
Tanja

Dumpfbacke 2. Aug 2007 05:57

Re: Datensätze vergleiche
 
Zitat:

Zitat von marabu
Hallo Tanja,

eine weitere Möglichkeit: Vor dem Laden der Dateien ein Feld mit dem Hash-Wert aller Feldinhalte hinzufügen - oder auch nach dem Laden über eine MD5 UDF, einen Index auf den Hash setzen und ein UPDATE mit dem bereits gezeigten Sub-Select.

Freundliche Grüße

Hallo marabu,
kannst du mir sagen so ich so einen UDF bekommen kann und wie "Breit" dann der Hash-Wert ist. Dann würde ich es in eine neue Spalte einfügen und einen Index erzeugen. Dann sollte es ja schneller gehen.

Danke Tanja

hoika 2. Aug 2007 07:30

Re: Datensätze vergleiche
 
Hallo Tanja,

nimm mal eine kleine Tabelle und probier das mal aus

SQL-Code:
select * from
personal where not exists (select id from personal)
Im Bsp ist Personal die Tabelle und Id der PrimKey.
Das muss auch unter IB6 gehen.

btw: welche Version von IB6 ist drauf ?


Heiko

Dumpfbacke 2. Aug 2007 07:43

Re: Datensätze vergleiche
 
Zitat:

Zitat von hoika
Hallo Tanja,

nimm mal eine kleine Tabelle und probier das mal aus

SQL-Code:
select * from
personal where not exists (select id from personal)
Im Bsp ist Personal die Tabelle und Id der PrimKey.
Das muss auch unter IB6 gehen.

btw: welche Version von IB6 ist drauf ?


Heiko

Hallo Heiko,
ich habe hier die alte Version 6. Mit dem oben vor Dir geschrieben Select geht es zum Teil. Es kommt keine Fehlermeldung mehr wenn nicht kein Feldname hinter dem Where eingebe. Nur leider ist das Ergebis auch falsch, es kommt immer NULL und keine Ergebnismenge.

Tanja

DeddyH 2. Aug 2007 07:53

Re: Datensätze vergleiche
 
Zitat:

Zitat von Dumpfbacke
Nur leider ist das Ergebis auch falsch, es kommt immer NULL und keine Ergebnismenge.

Klar kommt kein Ergebnis, es sollte wohl keinen Datensatz ohne Primärschlüssel geben. :zwinker:

Dumpfbacke 2. Aug 2007 07:57

Re: Datensätze vergleiche
 
Zitat:

Zitat von DeddyH
Zitat:

Zitat von Dumpfbacke
Nur leider ist das Ergebis auch falsch, es kommt immer NULL und keine Ergebnismenge.

Klar kommt kein Ergebnis, es sollte wohl keinen Datensatz ohne Primärschlüssel geben. :zwinker:

Bei den zweiten Select habe ich es mittels where auf die hälfte der Datensätze begrenzt.

Tanja

alzaimar 2. Aug 2007 08:02

Re: Datensätze vergleiche
 
Also:
1. Ein UDF ist eine 'User Defined Function'. Wie das genau mit IB6 geht, weiss ich nicht, aber man wird dir bestimmt helfen.

Dessenungeachtet reicht es u.U. aus, für beide Tabellen einen Index auf ein Feld zu setzen, von dem man ausgehen kann, das es fast nur unterschiedliche Werte enthält (Den Namen z.B.).

Dann vergleicht man beide Tabellen mit einem Join. Das Liefert in relativ kurzer Zeit alle identischen Zeilen.
SQL-Code:
Select * 
from Tabelle1
     Join Tabelle2 on Tabelle1.IndexFeld = Tabelle2.IndexFeld
   and Tabelle1.Feld1  = Tabelle2.Feld1
   and Tabelle1.Feld2  = Tabelle2.Feld2
   ...
Wenn man nur die Unterschiede möchte, dann verwendest Du einfach einen Full Join:

SQL-Code:
Select * 
from Tabelle1
     Full Join Tabelle2 on Tabelle1.IndexFeld = Tabelle2.IndexFeld
   and Tabelle1.Feld1  = Tabelle2.Feld1
   and Tabelle1.Feld2  = Tabelle2.Feld2
   ...

where Tabelle1.IndexFeld is null
   or Tabelle2.IndexFeld is null
willst Du nur die Datensätze, die in Tabelle1 ABER NICHT in Tabelle2 sind, dann einen LEFT JOIN
SQL-Code:
Select * 
from Tabelle1
     LEFT Join Tabelle2 on Tabelle1.IndexFeld = Tabelle2.IndexFeld
   and Tabelle1.Feld1  = Tabelle2.Feld1
   and Tabelle1.Feld2  = Tabelle2.Feld2
   ...

where Tabelle2.IndexFeld is null
Das sollte auch bei 800.000 Zeilen in vertretbarer Zeit durchzuführen sein. Bei SQL gilt: Probieren und Indexieren.

Um nun die Zeilen eindeutig zu identifizieren, solltest du ihnen vorher eine 'AutoInc'-Spalte, also einen PrimaryKey verpassen.

DeddyH 2. Aug 2007 08:06

Re: Datensätze vergleiche
 
Ein IMHO gute Seite zu dem Thema ist diese hier

marabu 2. Aug 2007 10:44

Re: Datensätze vergleiche
 
Hallo Tanja,

Zitat:

Zitat von Dumpfbacke
... kannst du mir sagen so ich so einen UDF bekommen kann und wie "Breit" dann der Hash-Wert ist. ...

ich habe zwei UDF Libraries gefunden, eine von Safa Rimeh (commercial) und eine von Richard Kotal (free).

Es ist eine hohe Kunst eine Aufgabenstellung so zu beschreiben, dass die Hilfestellung eines Unbeteiligten keinen schalen Beigeschmack hinterlässt. Bei deinem Problem irritiert mich, dass du zwei Textdateien vergleichen sollst (was man mit drei Unix Text Tools schnell erledigt hat) und diese Dateien im CSV-Format zu dir gelangen (was bedeutet, dass sie wohl Export-Dateien sind).

Auch weiß ich nicht, ob du diesen Vergleich regelmäßig oder einmalig durchführen willst und wie du das Ergebnis zurückgeben sollst. Ich gehe also einfach weiter davon aus, dass du lediglich ein performantes UPDATE-Statement für Interbase 6 suchst. Für eine optimale Lösung deines Problems müsste man statistische Informationen über deine Daten haben, wie alzaimar versteckt angedeutet hat.

Aber alles in allem sollten zwei mal 1 Mio Datensätze noch kein richtiges Problem darstellen. Um der Ungewissheit des Laufzeitverhaltens zu entgehen, würde ich zwei samples (1% und 5%) erstellen und mit denen die Zeit nehmen. Danach weißt du wie dein UPDATE-Statement skaliert und kannst die Wartezeit für den full set abschätzen und dein performance tuning anpassen.

SQL-Code:
UPDATE tabelle2
  SET datum = CURRENT_DATE()
  WHERE hash NOT IN (SELECT hash FROM tabelle1)
Freundliche Grüße

Dumpfbacke 2. Aug 2007 11:18

Re: Datensätze vergleiche
 
Zitat:

Zitat von marabu
Hallo Tanja,

ich habe zwei UDF Libraries gefunden, eine von Safa Rimeh (commercial) und eine von Richard Kotal (free).

Es ist eine hohe Kunst eine Aufgabenstellung so zu beschreiben, dass die Hilfestellung eines Unbeteiligten keinen schalen Beigeschmack hinterlässt. Bei deinem Problem irritiert mich, dass du zwei Textdateien vergleichen sollst (was man mit drei Unix Text Tools schnell erledigt hat) und diese Dateien im CSV-Format zu dir gelangen (was bedeutet, dass sie wohl Export-Dateien sind).

Auch weiß ich nicht, ob du diesen Vergleich regelmäßig oder einmalig durchführen willst und wie du das Ergebnis zurückgeben sollst. Ich gehe also einfach weiter davon aus, dass du lediglich ein performantes UPDATE-Statement für Interbase 6 suchst. Für eine optimale Lösung deines Problems müsste man statistische Informationen über deine Daten haben, wie alzaimar versteckt angedeutet hat.

Aber alles in allem sollten zwei mal 1 Mio Datensätze noch kein richtiges Problem darstellen. Um der Ungewissheit des Laufzeitverhaltens zu entgehen, würde ich zwei samples (1% und 5%) erstellen und mit denen die Zeit nehmen. Danach weißt du wie dein UPDATE-Statement skaliert und kannst die Wartezeit für den full set abschätzen und dein performance tuning anpassen.

SQL-Code:
UPDATE tabelle2
  SET datum = CURRENT_DATE()
  WHERE hash NOT IN (SELECT hash FROM tabelle1)
Freundliche Grüße

Hallo marabu
Ich habe mir die UDF mal gezogen und werde es mal prüfen. Die Daten würde ich schön öfters bekommen und auswerten. Das Ergebnis sollte dann in der Datenbak weiter verarbeitet werden.

Tanja

hoika 2. Aug 2007 11:23

Re: Datensätze vergleiche
 
Hallo Tanja,

mein SQL-Code sllte ja nur zeigen,
dass Interbase6 sehr wohl das exists kennt.
Die Nutzung von ist angeblich schneller als IN.

Zur Performance.
Warum einen Hash erzeugen, wenn es mit Concat
(wie in meinem Bsp mit dem SumFeld) auch geht.

OK, das mit dem einfachen Zusammenziehen war nicht so gut,
aber ein feld1 || , feld2 || ,

sollte doch reichen ?


Heiko

Dumpfbacke 2. Aug 2007 12:02

Re: Datensätze vergleiche
 
Zitat:

Zitat von hoika
Hallo Tanja,

mein SQL-Code sllte ja nur zeigen,
dass Interbase6 sehr wohl das exists kennt.
Die Nutzung von ist angeblich schneller als IN.

Zur Performance.
Warum einen Hash erzeugen, wenn es mit Concat
(wie in meinem Bsp mit dem SumFeld) auch geht.

OK, das mit dem einfachen Zusammenziehen war nicht so gut,
aber ein feld1 || , feld2 || ,

sollte doch reichen ?


Heiko

Hallo Heiko,
ja es reicht schon, jedoch habe ich es nach ca. 2 Stunden abgebrochen. Es kann ja noch Tage laufen bzw. in 5 Minuten fertig sein.
Tanja

hoika 2. Aug 2007 12:28

Re: Datensätze vergleiche
 
Hallo Tanjy,

was dauert denn so lange, schon das Erzeugen von SumFeld ?
oder die nachfolgende Query ?


Heiko

Dumpfbacke 2. Aug 2007 15:51

Re: Datensätze vergleiche
 
Zitat:

Zitat von hoika
Hallo Tanjy,

was dauert denn so lange, schon das Erzeugen von SumFeld ?
oder die nachfolgende Query ?


Heiko

Hallo Heiko,
das Summenfled ist kein Problem. Dauert ca. 3-5 Minuten. Nur dann die Query habe ich nach 2 Stunden mal abgebrochen.

Tanja

hoika 2. Aug 2007 17:10

Re: Datensätze vergleiche
 
Hallo Tanja,

1. zeig noch mal die Query

2. nimm etwa 1000 Einträge pro Tabelle
und teste die Query im IBPlanalyzer



Heiko

Hansa 2. Aug 2007 19:13

Re: Datensätze vergleiche
 
Zitat:

Zitat von Dumpfbacke
...Es liegen zwei CSV Dateien mit jewals fast 800.000 Datenstzäte vor. Diese beiden Dateien habe ich ich zwei Tabellen im Interbase geschrieben...

Tabelle 2 soll also auf dem neuesten Stand sein, in Abhängigkeit von Tabelle 1 ?

Zitat:

Zitat von Dumpfbacke
...Nun wollte ich in alle Datensätze in der Tabelle2 das aktuelle Datum schreiben, wenn die Datensatz in der Tabelle1 vorhanden ist. Somit müßte der rest ohne Datum dann neu sein oder geändert worden.

Na, dann muss die Tabelle 2 wohl sequentiell durchlaufen werden (Sortierung spielt keine Rolle, da es sowieso jeden DS in Tabelle 2 betrifft). DS in Tabelle 1 vorhanden => Datum setzen. Habe ich das richtig verstanden ? Falls ja, dan würde ich folgende stored Procedure bauen und über die Tabelle 2 laufen lassen (geht auch ohne EXISTS) :

SQL-Code:
CREATE PROCEDURE NEUTABLESP (
    ID,
    FELD1 VARCHAR (...
...
    FELD6
As
Declare Variable VORHANDEN Integer;
BEGIN
  VORHANDEN = -1;
  SELECT ID FROM TABLE1 WHERE (FELD1= :FELD1) AND
...
     (FELD6= :FELD6) INTO :VORHANDEN;
  IF (VORHANDEN >= 0) THEN BEGIN
    UPDATE TABLE2 SET DATUM=CURRENT_TIMESTAMP
    WHERE (FELD1= :FELD1) AND
...
     (FELD6= :FELD6)
  END
  SUSPEND;
END^
Nicht getestet ! So würde ich zumindest mal anfangen. :mrgreen:

grenzgaenger 2. Aug 2007 20:49

Re: Datensätze vergleiche
 
@hansa, die sortierung spielt soweit eine rolle, dass bei zwei unsortierten datensätzen, die eine datei immer wieder vom beginn an gelesen werden muss, was sich auf die laufzeit niederschlägt. wenn beide sortiert sind, dann braucht jede tabelle exact 1x durchlaufen werden und alle änderungen, inserts, deletes sind ermittelt.

@Dumpfbacke, dann kannste ja auch die sortierfunktion deiner datenbank nutzen, wenn du die flat files nicht sortieren möchtest. da brauchste aber zwei cursor nach folgendem schema...
SQL-Code:
select * from tab1 order by ...
und
SQL-Code:
select * from tab2 order by ...
wobei die sortieroptionen die selben sidn. und dann einfach wie bei zwei flat files durchschleifen... ein durchlauf über tab1 und die tab2 als slave und wenn du am ende angekommen bist, haste alle infos.

grüsse
gg

Hansa 2. Aug 2007 21:04

Re: Datensätze vergleiche
 
Wozu soll denn da die Sortierung eine Rolle spielen ? Wozu soll das gut sein ? :gruebel: Nochmals grob mein Vorschlag : sequentiell über Tabelle 2 wandern. Bei jedem Datensatz anhalten und die SP ausführen. Die soll in Tabelle 1 gucken, ob ein gleicher Datensatz existiert oder nicht. Falls ja => aktuellen Datensatz von Tabelle 2 updaten (Datum setzen) -> nächster DS von Tabelle 2. Selbes Spielchen durchführen bis EOF von Tabelle 2. DS, die in beiden Tabellen vorhanden sind haben dann ein Datum und die nicht in Tabelle 1 enthaltenen eben nicht. Und fertig. :mrgreen:

alzaimar 2. Aug 2007 21:42

Re: Datensätze vergleiche
 
Prinzipiell hat Hansa recht. Nur ist IB/FB keine DBISAM-DB, sondern ein RDBMS. Hier wird mit Mengen gearbeitet. Die verhalten sich ohne Index intern genauso wie eine DBISAM, aber bei richtigen Indexen wird es verdammt schnell. Dann greifen eben B-Tree-Algorithmen, die pro Datensatz gegen O(1) gehen, also nahezu unabhängig von der Anzahl der Datensätze ist. Bei 800.000 macht das schon den Unterschied zwischen Stunden und Sekunden aus. Ich traue mir zu, bei 1-2 Mio Datensätzen ein Self-Join in ein paar Sekunden hinzubekommen.

Aber mir is det sowieso allet ejal weil ick morjen in Uuuurlaub fliegen tu! :mrgreen: :mrgreen:

grenzgaenger 2. Aug 2007 23:25

Re: Datensätze vergleiche
 
@hansa: tja, weil man dann nicht mehr sortieren braucht. so 'n ascii file, sortiert das BS mit 'n paar parametern problemlos... und dann läuft der vergleich, auch ohne DB in 'n paar sekunden durch.

@alzaimar: mit den ständigen zugriff auf die DB, kann es schon länger brauchen. aber bei zwei sortierten sequentziellen dateien (master --> slave) ist die laufzeit O(n). er liest exakt 2x 800'000 datensätze und die sache ist erledigt. da brauchts auch keinen index oder so was ...nur sortiert müssen die beiden tabellen sein.

einen solchen fall, hatte ich schon lange nicht mehr. aber damals mit COBOL lieb das ganze in 'n paar sekunden (auf 'ner alten architektur [286 war es glaub ich]) durch. ansonsten einfach mal nach den stichwörtern "normierte programmierung", "gruppenwechsel" oder "sequentielle dateiverarbeitung" suchen. da stehen die standardprobleme (vor der datenbankzeit) mit sicherheit ausführlich beschrieben...

grüsse und noch 'n schönen abend
gg

Hansa 3. Aug 2007 12:04

Re: Datensätze vergleiche
 
Liste der Anhänge anzeigen (Anzahl: 2)
Mehr ist das nicht :

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DB, FIBDataSet, pFIBDataSet, FIBDatabase, pFIBDatabase,
  FIBQuery, pFIBQuery, pFIBStoredProc;

type
  TForm1 = class(TForm)
    Database: TpFIBDatabase;
    Transaction: TpFIBTransaction;
    Test1DS: TpFIBDataSet;
    Test2DS: TpFIBDataSet;
    Button1: TButton;
    Memo1: TMemo;
    TestSP: TpFIBStoredProc;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
  i := 0;
  Test1DS.close;
  Test1DS.SelectSQL.Text := 'SELECT * FROM TEST1';
  Test1DS.Open;
  while not Test1DS.Eof do begin
    i := i + 1;
    TestSP.ParamByName('Feld1').AsString := Test1DS.FieldByName ('Feld1').AsString;
    TestSP.ParamByName('Feld2').AsString := Test1DS.FieldByName ('Feld2').AsString;
    TestSP.ParamByName('Fled3').AsString := Test1DS.FieldByName ('Fled3').AsString;
    TestSP.ParamByName('Feld4').AsString := Test1DS.FieldByName ('Feld4').AsString;
    TestSP.ParamByName('Feld5').AsString := Test1DS.FieldByName ('Feld5').AsString;
    TestSP.ParamByName('Fled6').AsString := Test1DS.FieldByName ('Fled6').AsString;
    TestSP.ExecProc;
    Memo1.Lines.Add(IntToStr (i));
    Test1DS.Next;
  end;
  Transaction.Commit;
  Database.Close;
  showmessage ('fertig !');
  Close;
end;

end.
Inkl. übernommene Schreibfehler. :mrgreen: Im Anhang sind 2 DBs. Da drin ist auch die SP. TESTDB2.FDB ist der Ursprungszustand TESTDB.FDB der Zustand der DB nach Programmlauf. Und Grenzgänger : sortiert ist da nichts. :-D

grenzgaenger 3. Aug 2007 17:24

Re: Datensätze vergleiche
 
klar hansa, es geht auch ohne sortieren. da erschlägt man dann das problem mit mehr rechenleistung :-) . aber das hat man ja heutzutage :-)

die lösung mit den zwei sortierten flat files, kommt mit vielleicht 50kb hauptspeicher aus und braucht keine datenbank sondern nur zwei open und readln... ;-)

das ging etwa so...
Delphi-Quellcode:
open master; open slave;
master.first; slave.first;
while not master.eof do
begin
 if master.record > slave.record then
 begin
  writeln('gelöschter slave record: ', slave.record);
  slave.next;
 end
 else
  if master.record = slave.record then
  begin
   writeln('master record = slave record');
   slave.next;
  end
  else
  begin //master.record < slave.record
   writeln('neuer slave record', slave.record);
  end;
 master.next;
end;
while not slave.eof do //noch datensätze in slave übrig?
begin
 writeln('neuer slave record: ', slave.record);
 slave.next;
end;

close master; close slave;
das hier wär da auch schon der ganze code ;-) . also so komplex ist das mit den zwei sortierten flat fies gar nicht und da sortiert auch sehr schnell ;-)

grüsse und noch 'n schönes weekend
gg


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:36 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