Auswertung große DBF/komplexe Filter beschleunigen

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Benutzeravatar
Christof
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Mo, 01. Okt 2007 17:14
Wohnort: Bedburg
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Christof »

Hallo Jan,

ich glaube, das habe ich einigermaßen verstanden. Dann muss ich die einzelnen Datensätze aus der DBF z.B. mit einer DO...WHILE oder mit einem DBEVAL holen und mit SCATTER ins DO bringen. Der Tipp mit dem alias->(recno()) ist sehr gut.
Zurückschreiben funktioniert dann ähnlich mit Gather. Da muss ich mir dann alle Sätze aus dem DO holen und verarbeiten.

Das Arbeiten mit dem SELECT hat evt. auch Charme. Wie ich die DBF auslese und evt. auch in ein DO bringe konnte ich einigermaßen aus der Doku entnehmen. Im Moment hänge ich noch ein bisschen an dem Punkt, wie ich einen geänderten Resultset wieder (in einem Rutsch?) in die DBF kriege.

Ich muss mir mal ein kleines "Labor" dafür anlegen.

Viele Grüße, schönes Wochenende

Christof
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Jan »

Christof,

Du könntest Dir ja auch noch eine MemVar anlegen oDo[j]:geaendert := .F. . Und nur da, wo sich etwas geändert hat, werden auf .T. gesetzt und beim Zurückschreiben auch berücksichtigt.

Klar ist SELECT auch super für diesen Zweck. Aber wie gesagt - Manfred hat da Speicherverluste entdeckt (PDR 7309). Wenn Alaska das schnell gelöst bekommen wäre das natürlich super. Dann wäre nur zu überlegen wie man da den RecNo() mit rein bekommt. Mir persönlich wäre es zu riskant etwas zurück zu schreiben von dem ich nicht weiß, ob ich dafür wirklich auf dem richtigen Satz stehe.

Jan
Zuletzt geändert von Jan am Fr, 17. Jul 2020 15:17, insgesamt 1-mal geändert.
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Christof
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Mo, 01. Okt 2007 17:14
Wohnort: Bedburg
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Christof »

Ich glaube, es gibt noch eine ganz andere Hürde...

Kann es sein, dass ich mit meiner - etwas älteren - Foundation gar keine SQL-Statements "herstellen" kann? :?

Egal... das mit dem DataObject probiere ich mal aus. Aber nicht mehr heute.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Jan »

Christof,

OK. Foundation. Da war auch irgend was mit SQL. Manches geht, manches nicht. Aber SELECT sollte gehen. In der Hilfe unter "SELECT (SQL)" sehe ich, daß das für Foundation freigegeben ist. Was nur in der Professional geht ist die PostreSQL DBE. Aber die willst Du ja im Moment auch nicht nutzen.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21165
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 206 Mal
Danksagung erhalten: 67 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Manfred »

vielleicht liege ich ja auch total falsch, aber mein SELECT bezieht sich auf Directory() in DataObjects und nicht auf irgendwelche Tabellen.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
Christof
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Mo, 01. Okt 2007 17:14
Wohnort: Bedburg
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Christof »

Hallo Manfred,

wenn das so ist, ist es nicht das, was ich möchte. Ich möchte per Select auf eine DBF zugreifen und diese ggf. komplett in ein DO überführen, um sie dann von dort aus bearbeiten und am Ende wieder zurückschreiben zu können. Habe aber noch nicht raus, wie das geht.

Im Prinzip wäre auch sowas wie eine RAMDisk nützlich. Dann bräuchte ich wahrscheinlich kaum etwas umzustellen.

VG
Christof
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Jan »

Manfred,

keine Ahnung ob es da einen Unterschied geht. Es geht bei beidem um ein SELECT, das irgend welche Daten in ein Dataobject in einem Array schaufelt. Müsste man testen ob das auch bei dbf die Speicherprobleme gibt.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21165
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 206 Mal
Danksagung erhalten: 67 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Manfred »

Hi Christof,
ich benutze SELECT nur bei ADS, oder demnächst bei PostGre. Nicht aber bei normalen DBF. Deshalb war ich etwas erstaunt über Jans Aussage.
Gruß Manfred
Mitglied der XUG Osnabrück
Schatzmeister des Deutschsprachige Xbase-Entwickler e.V.
großer Fan des Xbaseentwicklerwiki https://wiki.xbaseentwickler.de/index.p ... Hauptseite
Doof kann man sein, man muß sich nur zu helfen wissen!!
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von AUGE_OHR »

Christof hat geschrieben: Do, 09. Jan 2014 9:18 die Idee mit dem temporären Index ist im Grunde gut. Ich fürchte nur, der Indexausdruck wird ziemlich komplex und ob (dann) der Aufbau schneller ist, als gleich über einen Filter zu arbeiten müsste ich mal testen.
ich sehe keine Probleme einen "Custom Index" zu verwenden.

mit OrdKeyAdd() wird der Schlüsselwert aufgenommen wenn die FOR-Bedingung erfüllt wird.
ich habe dazu ein "Dummy" Feld in der DBF und suche im Memo nach einer Bedingung.

Code: Alles auswählen

// CUSTOM Index need "dummy" Field
INDEX ON ZAHLUNG->ZDUMMY TAG "FTS" TO "ZAHL_FTS.NTX" CUSTOM
? IndexKey()
OrdSetFocus(0)

nStart := SECONDS()
Ondummy("Start",TIME() )
GO TOP
DO WHILE !EOF()
   // next Memo
   FTS_MEMOADD(ZAHLUNG->ZZUSATZ)
   SKIP
ENDDO
Ondummy("Stop",SECONDS()-nStart )

Code: Alles auswählen

FUNCTION FTS_MEMOADD(cZUSATZ)
LOCAL aText
LOCAL i,iMax

// split text into single word and add it into Array
aText := AtInside( " ",cZUSATZ)
iMax := LEN(aText)

IF iMax > 0
   FOR i := 1 TO iMax
      Ondummy(RecNo(), aText[i] )
      // NEED "dummy" Field
      REPLACE ZAHLUNG->ZDUMMY WITH aText[i]
      // add to Index
      OrdKeyAdd( "FTS")
   NEXT
ELSE
ENDIF
RETURN .T.
zu "auswerten" des Index nehme ich OrdWildSeek()

Code: Alles auswählen

OrdSetFocus("FTS")
SEEK("verrechnet")
? FOUND()
WAIT

Ondummy("Start",TIME() )
? OrdWildSeek("verrechnet")
DO WHILE Found()
   cDummy := &( OrdKey() )
   Ondummy("Treffer:",RecNo(),"Schluessel:",cDummy )
   AADD(aArray,cDummy)
   OrdWildSeek()
ENDDO
? LEN(aArray)
Ondummy("Stop",SECONDS()-nStart )
gruss by OHR
Jimmy
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Dieter »

Hallo Christof,

du schreibst:
Das Problem ist, dass die Arbeiten auf den DBFs jetzt extrem verlangsamt sind, weil die Verbindung zu den Netzlaufwerken in die Knie geht. Und wenn dann eine Bearbeitung mit

Do while !eof()
...
skip()
enddo

erfolgt, hat man halt bei jedem Datensatz Traffic auf der Leitung.
Das schreit nach einer Terminalserver-Lösung. Dein Programm sollte auf einem entfernten Terminalserver arbeiten, auf das der User ( du schreibst nur ein Anwender mit Exclusiv-Rechten) per Remotekonsole zugreift. Der Datentraffic (Bildschirminhalte) beträgt dann nur 1-3 Mbit/s und die Anwendung sollte bei einem vernüftig ausgestatteten Server schneller laufen, als auf einem Einzelplatzrechner.
Ich habe die Erfahrung gemacht, dass das Einlesen in Speicherarrays häufig mehr Zeit in Anspruch nimmt, als die anschließenden Berechnungen mit den Speicherarrays. Die Umprogrammierung ist außerdem zeitaufwendig und lohnt wirklich nur, wenn sichergestellt wird, dass merklich Laufzeit eingespart wird.
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Benutzeravatar
Christof
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Mo, 01. Okt 2007 17:14
Wohnort: Bedburg
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Christof »

Hallo Dieter,

das ist in der Tat eine Option. Tatsächlich geht das auch, wird aber nur von 1 Kunden bisher genutzt. Grund ist, dass der Server von einem GUT abgeschirmten Rechenzentrum betrieben wird, die Installation nicht wirklich einfach ist und die Handhabung des Programms dann auch die Einfachheit verliert, mit der es die ganze Zeit gepunktet hat. :-(

Naja... vielleicht ist es nach 20 Jahren einfach mal Zeit das Ding einzumotten... Schnief...

Trotzdem vielen Dank!

Viele Grüße

Christof
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Werner_Bayern »

Servus Christof,

es gibt m. W. n. nur eine Lösung, die das ganze schneller macht, unter der Voraussetzung:

- "lohnt nicht" => kein Budget für SQL-Umstellung - wäre beste Lösung
- Index über die entsprechenden Felder in Verbindung mit ordwildseek nicht möglich
- Terminalserver nicht möglich (was ich persönlich nicht verstehe, TS geht immer)

Die DBF lokal ins TEMP-Verzeichnis (getenv("temp")) kopieren. Nicht aber mit dbf-Funktionen, sondern mit copy file, weil das um ein x-faches schneller geht. Auch hier gibt's eine Menge Möglichkeiten, um die schnellste Variante zu wählen: Selbst mit den f-Functionen von Xbase++ und mit den Blockgrößen testen, oder ein RunShell() / shellexecuteA mit z. B. xcopy.

Wenns um Abgleich von Änderungen Server auf lokal geht, gibt's auch einige Strategien, wie man das möglichst effizient macht.

Lokal dann die Abfragen durchführen und Änderungen schreibst einfach satzweise auf den Server zurück.

Bei der Optimierung der Abfragen hast ja schon die besten Tipps bekommen.

Wir hatten diese Woche bei einem Kunden von seiner Fremd-WW - bei der der Hersteller und jeder andere Fremdhersteller unserem Kunden sagte, eine Datenübernahme sei nicht möglich - 740.000 Artikel übernommen. Die DBF hat 1.8 GB und liegt bei unserer WW immer auf dem Server. Der Zugriff über ordwildseek - wir suchen da in 3 großen Textfeldern - geht sehr schnell, nach ca. 2-3 Sekunden sind die ersten Treffer da.

Alternativ wäre eine 2. mögliche Lösung in so einem Falle einen kleinen Dienst zu schreiben, der auf dem Server läuft. Ist vermutlich in 20 Minuten programmiert. Der wartet auf einen Befehl vom Client, der die Filterbedingung enthält, diese dann am Server ausführt und das Ergebnis in eine Temp-dbf schreibt.

Vielleicht wird es nach 20 Jahren mal Zeit für ein Redesign :wink:
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Christof
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 265
Registriert: Mo, 01. Okt 2007 17:14
Wohnort: Bedburg
Hat sich bedankt: 1 Mal
Danksagung erhalten: 1 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Christof »

Hallo Werner,

danke für die ausführliche Beschäftigung mit dem Thema. Die Option, die Dateien in das örtliche Tempverzeichnis zu kopieren klingt erstmal nicht schlecht. Bin mir nur nicht sicher, ob das auch tatsächlich immer wirklich lokal liegt. Wenn das dann auch auf dem Netzlaufwerk liegt, habe ich nichts gewonnen. Das Problem sind nicht die Indices oder die Suchvorgänge nach einzelnen Sätzen. Es finden halt viele Bearbeitungen statt, die über bis zu 100.000 Datensätze gehen. Ungefähr so:

Do while !eof()

if (a=b .and. c=d .and. y=x) .or. Hugo=.T.
replace alias->feld with "Chaka"
endif
dbskip()

enddo

Einige Schleifen habe ich auch schon auf dbEval() umgestellt. Hat hier und da was gebracht, löst aber nicht grundsätzlich das Problem.

Die Schleifen sind aber viiiiiiiiel komplexer gefüllt, weil es eben ein Fülle von Parametern und Bedingungen gibt. Einer Datenbank würde ich "einfach" sagen "Select .... where... order by..." oder eben sowas wie "Update alias set feld="Hugo" where..." und die würde das dann auf dem zentralen Rechner ausführen und mir das Ergebnis liefern. Bei der satzweisen Abarbeitung holt sich Xbase halt immer den Satz vom entfernten Server, macht was damit und schreibt ihn dann wieder zurück.

Und.. "ja", ein Redesign wäre nach 20 Jahren durchaus mal angebracht, aber... es fehlt - wie immer - die Zeit dazu und die relativ kleine Anzahl von Kunden macht es auch wirtschaftlich nicht wirklich interessant.

Viele Grüße

Christof
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Auswertung große DBF/komplexe Filter beschleunigen

Beitrag von Werner_Bayern »

Bitte - und danke für die ausführliche Antwort.

Ok, dann vermutlich wirklich Schnief...

wenn für eine Anwendung mit so vielen Daten mit so vielen Änderungen (100.000) kein Geld (mehr) gezahlt wird...
es grüßt

Werner

<when the music is over, turn off the lights!>
Antworten