Filter für enthaltene Fields in NTX - Indexdatein

Zugriff, Engines, Konvertierung. Von ADS über DBF bis zu SQL.

Moderator: Moderatoren

Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

Filter für enthaltene Fields in NTX - Indexdatein

Beitrag von Krause »

Hi,

kennt jemand eine effiziente Möglichkeit, aus den Ergebnissen von OrdKey() und OrdFor() (NTX - Index) die darin enthalten Field Namen der Datenbank herauszufiltern? Sinn und Zweck dieser Funktionalität ist es, bereits im Vorfeld eines Schreibzugriffes auf die Datenbank zu entscheiden, welche der vorhanden Indexdateien geöffnet werden müssen (es ist hier schon bekannt, zu welchem Field es eine Änderung gegeben hat).

Mit freundlichen Grüßen
Joachim Krause
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Filter für enthaltene Fields in NTX - Indexdatein

Beitrag von AUGE_OHR »

hi,
Krause hat geschrieben: kennt jemand eine effiziente Möglichkeit, aus den Ergebnissen von OrdKey() und OrdFor() (NTX - Index) die darin enthalten Field Namen der Datenbank herauszufiltern?
es sind doch nur cString die zu zurück bekommst, Als "Trenner" hast du
beim aufbau des Index ja "+" benutzt ...
Krause hat geschrieben: Sinn und Zweck dieser Funktionalität ist es, bereits im Vorfeld eines Schreibzugriffes auf die Datenbank zu entscheiden, welche der vorhanden Indexdateien geöffnet werden müssen (es ist hier schon bekannt, zu welchem Field es eine Änderung gegeben hat).
sorry aber da muss ich mal einharken : Man mach IMMER ALLE Index
Dateien die zu eine DBF gehören ZUSAMMEN auf. Danach kannst du
dann mit SET ORDER ( DbSetOrder() ) den "kontrollierenden" Index
einstellen.

Wenn du z.b. "nur" 1 von 3 Index Datein aufmachst und ein "update"
darauf ausführst und nicht auf die beiden anderen so wirst du irgendwann
einen 1210 (Cl*pper) Fehler beim öffnen der DBF bekommen.

gruss by OHR
Jimmy
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Beitrag von Rolf Ramacher »

Hi Joachim,

kurze Anmerkung zu Jimmy's Kommentar. Wie er schon sagte alles in eine Index-Datei. Oder du machst es wie ich. Arbeite mit Tag-Namen,
dabei brauchst du kein Set Order und arbeitest, wenn die die Index auswählen willst mit (Datenbank)->(OrdSetfocus())
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

Beitrag von Krause »

Hi Jimmy,

wir haben unsere Programme etwas anders als "Normal" aufgebaut. Prinzipell "öffnen" wir nur Datenbanken / Dateien wenn wir einen Zugriff benötigen.
Im Klartext, eine Applikation unterhält im "Ruhezustand" keine verbindung zum Server. Ein internes dynisch aufgebautes Dictionary sowie ein ausgeklügeltes Cachesystem garantieren ein problemloses Arbeiten mit allen möglichen Datenquellen (DBF, ASCII, ADS, SQL etc.) Gesteuert wird dieses Sytem allein nur über im Dictionary verwalteten ALIAS-Namen. Realisiert wird das ganze durch eine speziell für diesen Aufgabenbereich entwickelte DLL.

Für alle Lesezugriffe werden zum Bsp. die Datenbanken Readonly / Shared geöffnet, hierbei wird nur noch der aktive Index mitgeöffnet. Dieses System arbeitet bei uns seit der Version XBase 1.8.2 problemlos.

Für alle Schreibzugriffe werden die Datenbanken Exclusive geöffnet. Hier machen wir im Moment noch alle INDEX-Dateien auf. Dieses möchte ich jedoch dahin ändern, dass ich nur noch die notwendigen Indexdateien aufmache.

Mitt diesem Verfahren arbeiten wir derzeit mit ca. 124 Arbeitsplätzen gleichzeiteig in ein und dem selben Datenbestand.

Mit freundlichen Grüßen
Joachim Krause
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo,

solange nur gelesen wird, braucht man nicht alle Indexdateien öffnen,
beim Schreiben wird es aber gefährlich !
Wer will wirklich beurteilen, ob ein replace Indexrelevant ist oder nicht.

Jimmy hat mit seinem Kommentar auf jeden Fall recht, solange es sich nicht nur um readonly Dateien handelt.
Gruß
Hubert
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21189
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi,

nur mal ein kurzer Einwurf. Ist es nicht so, das bei geöffneten Indexdateien generell irgendwie geschrieben wird, wenn REPLACED wird, egal ob der Index geändert wird oder nicht? Ich meine ich habe es mal gehört und irgendwie im Debugger nachgesehen, wenn man z.B. eine Funktion in einem Index hat. Deshalb sollte man schon alle Indexdateien auf haben.
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
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo Manfred,

also erstens geht REPLACE nicht bei READONLY Dateien, somit habe ich ja empfohlen alle Indexe zu öffnen, ob immer etwas darein geschrieben wird, kann man in den Eigenschaften sehen. Wenn im Explorer die Zeiten des letzten Speicherns von Indexdateien zueinander und der DBF abweichen, dann trifft die Aussage nicht zu. Ohne eine nötige Änderung in eine Indexdatei zu schreiben wäre aber Zeitverschwendung, das kann ich mir nicht vorstellen. LUpdate() bezieht sich nur auf die DBF.
Gruß
Hubert
Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

Es könnte doch funktionieren ...

Beitrag von Krause »

Hi Hubert,


du schreibst:
Jimmy hat mit seinem Kommentar auf jeden Fall recht, solange es sich nicht nur um readonly Dateien handelt.
wie bereits vermerkt ...
(es ist hier schon bekannt, zu welchem Field es eine Änderung gegeben hat).
... kenne ich die Updateanforderung bezogen auf das einzelne Field /Column eines Records. Ich schreibe Prinzipiell nur nach einem Verify recordunabhängig über primary key zurück, kenne also SOLL und IST.
Diesbezüglich habe ich schon entsprechende Test durchgeführt, so lange man kein Update auf Indexrelevante Fields / Colums durchführt, kann man problemlos die (DBF) Datenbanken exclusive öffnen und Daten zurückschreiben ohne die Indexdateien ebenfalls öffnen zu müssen. Ein simples Beispiel wäre eine Kundendatenbank in der der Umsatz geändert wird und wobei der Umsatz nicht Indexrelevant ist.

In der Phase der Erstinitialisierung unseres dynamischen dictionary öffne ich beim ersten Zugriff alle Indexdateien, in diesem Zusammenhang könnte ich also aus den Rückgabewerten von OrdKey() und OrdFor() eine diesbezügliche „Fieldliste“ je Indexfile erstellen und abspeichen.

Mit freundlichen Grüßen
Joachim Krause


[/quote]
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Wenn du z.b. "nur" 1 von 3 Index Datein aufmachst und ein "update"
darauf ausführst und nicht auf die beiden anderen so wirst du irgendwann
einen 1210 (Cl*pper) Fehler beim öffnen der DBF bekommen.
Das ist einfach nicht richtig. Indexe werden aktualisiert, wenn sich die Satzreihenfolge oder -anzahl ändert (z.B. durch DbPack, DbAppend, mit DbDelete nur dann, wenn der Index die Kondition FOR !Deleted() hat), oder wenn sie inhaltlich betroffen sind. Wenn ich einen Index auf das Feld NAME habe und pausenlos VORNAME ändere, brauche ich den Index auf NAME nicht. Er ändert sich nicht. Und einen Korruptionsfehler kann man, wenn man das sorgfältig macht, auf diese Art auch nicht erzeugen.

@Manfred: Indexdateien werden normalerweise (DBFNTX) bei jeder Dateioperation - suchen, bewegen, ersetzen - vollständig gelockt (ro), aber wirklich nur für eine mikroskopisch kurze Zeit. Seit der 1.9 gibt es Extended Locking für Indexe, wobei dann tatsächlich nur betroffene Sätze gesperrt werden, aber auch bei allen Operationen.
Herzlich,
Tom
Benutzeravatar
Manfred
Foren-Administrator
Foren-Administrator
Beiträge: 21189
Registriert: Di, 29. Nov 2005 16:58
Wohnort: Kreis Wesel
Hat sich bedankt: 210 Mal
Danksagung erhalten: 67 Mal

Beitrag von Manfred »

Hi Tom,

ich lasse mich gerne belehren. Es war dann eine falsche Info, oder Beobachtung. Aber besser so als andersherum.
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
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Wie ein NTX-Index (Clipper; Alaska hat da ein bißchen dran rumgeschraubt, aber nicht essentiell) aufgebaut ist, kann man hier nachlesen:

http://www.wotsit.org/download.asp?f=ntx
Herzlich,
Tom
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16511
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Und ein kurzer Einwurf von mir:
Es müssen alle betroffenen Indexdateien geöffnet sein, sofern ein in den Indexen vorhandenes Schlüsselfeld in der Datenbank geändert wird!
Den Beweis habe ich bereits hier im Forum erbracht!
Sind die Indexdateien zum Zeitpunkt der Änderungen nicht geöffnet, ist ist ein reindex nötig!

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Martin.

Genau darum geht es Joachim ja. Er will ggf. Schlüsselfelder ersetzen und dafür nur diejenigen Indexdateien öffnen, die betroffen sind.

@Joachim: Aber ganz habe ich Deine Frage nicht verstanden.

Code: Alles auswählen

USE KUNDEN
INDEX ON name+vorname TO KUNDEN
SET INDEX TO KUNDEN
? OrdKey() // Antwort: name+vorname
? IndexKey() // Kompatiblitätsfunktion, gleiche Antwort
Wenn Du jetzt herausbekommen willst, welche Indexe geöffnet werden müssen, wenn ein bestimmtes Feld geupdated wird, mußt Du alle Indexe öffnen:

Code: Alles auswählen

FOR i := 1 to FCount()
  IF Upper(FieldName(i)) $ upper(OrdKey())
     * Dieser Feld ist, wenn der Name nicht Teil eines anderen Feldnamens
     * ist, im Index
   ENDIF
NEXT
Damit ist aber nichts gewonnen, Du mußt den Index ja öffnen. Du kannst Dir natürlich auch die Struktur einer NTX-Datei ansehen (siehe oben) und direkt in der Datei nach dem Feldnamen suchen. Aber Du schrubst etwas von wegen Ihr würdet eine Art Repository führen. Was spricht dagegen, solche Informationen dort vorzuhalten?
Herzlich,
Tom
Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

Das Problem im einzelnen ...

Beitrag von Krause »

Hi Tom,

du schriebst:
Damit ist aber nichts gewonnen, Du musst den Index ja öffnen.
das stimmt von Prinzip her, aber ich öffne alle Index Files (DBF) nur einmal bei der Erstinitialisierung meines internen und temporären (Lebensdauer nur während der Programmlaufzeit) Dictionary. Diese Dictionary beinhaltet alle relevanten Daten zu einer Datenbank (ähnlich wie bei ADS, nur ich verwalte intern alle Datenbanktypen, SOL Table, ASCII - Files etc.)
Die übergeordnete Instanz (zum Bsp. die EXE) registriert die Datenbank und kann dann danach nur über den Alias auf diese Datenbank zugreifen.
Sie weiß von Prinzip danach nicht mehr, um welche Datenbank es sich eigentlich wirklich handelt, der Zugriff ist intern standartisiert. Die EXE (Applikation) greift also auf eine DBF genauso zu wie auf eine Oracle Table.

Es geht mir eigentlich nicht nur um das öffnen oder nicht öffnen von Indexdateien, es geht auch um eine automatische Primary Key Verwaltung ähnlich SQL, das heißt aus UNIQE wird gegebenenfalls ein PRIMARY KEY.

Die Struktur der NTX Indexfile lese ich bereits im Vorfeld aus, es fehlt also der Filter. Indexbedingungen können sehr komplex sein, hier nur ein einfaches Beispiel:

WERK_NR+KUNDENNR+ IIF(EROF,"T","F")+IIF(FREI,"T","F")+IIF(EINST,"T","F")

Mit freundlichen Grüßen
Joachim Krause
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Beitrag von AUGE_OHR »

hi,
Tom hat geschrieben:
Wenn du z.b. "nur" 1 von 3 Index Datein aufmachst und ein "update"
darauf ausführst und nicht auf die beiden anderen so wirst du irgendwann
einen 1210 (Cl*pper) Fehler beim öffnen der DBF bekommen.
Das ist einfach nicht richtig. Indexe werden aktualisiert, wenn sich die Satzreihenfolge oder -anzahl ändert (z.B. durch DbPack, DbAppend, mit DbDelete nur dann, wenn der Index die Kondition FOR !Deleted() hat),
Ist das jetzt auf Cl*pper oder Xbase++ bezogen ?
Wenn Xbase++ : erinnerst du noch die v.1.3x und die "komischen"
Fehler wenn eine "SKIP" oder "GOTO" Fehler hatte ? Das hatte dann
immer was mit den Index zu tun auch wenn der nicht aktive war.
Tom hat geschrieben: oder wenn sie inhaltlich betroffen sind. Wenn ich einen Index auf das Feld NAME habe und pausenlos VORNAME ändere, brauche ich den Index auf NAME nicht. Er ändert sich nicht. Und einen Korruptionsfehler kann man, wenn man das sorgfältig macht, auf diese Art auch nicht erzeugen.
Ich werde dich ja kaum von deinen Glauben abbrngen lassen.
Im "Prinzip" sollte es zwar so sein, ist es aber unter Xbase++ NICHT !
Tom hat geschrieben: @Manfred: Indexdateien werden normalerweise (DBFNTX) bei jeder Dateioperation - suchen, bewegen, ersetzen - vollständig gelockt (ro), aber wirklich nur für eine mikroskopisch kurze Zeit. Seit der 1.9 gibt es Extended Locking für Indexe, wobei dann tatsächlich nur betroffene Sätze gesperrt werden, aber auch bei allen Operationen.
genau DAS meine ich und es ist nicht nur der "führende" Index oder der
betroffene. Mach doch mal folgenden Versuch :

USE TEST INDEX N1,N2,N3

so nun REPLACE mal ein FELD was zun Index N2 gehört. Nun schau dir
mal die *.DBF und die *.NTX an. ALLE habe nun die selbe Uhrzeit und
nicht nur die "bearbeitet" Index.

Das ist auch für mich der Hinweis das etwas mit dem Index nicht stimmt
wenn das Datum/Uhrzeit nicht stimmt ... dann ist ein reindex dran.

gruss by OHR
Jimmy
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Beitrag von Rolf Ramacher »

Hallo,

also nochmal wenn Datenbankeninhalte verändert werden, ändert sich auch der Index. Um Verwirrungen zu vermeiden, packe ich alle Index in eine Indexdatei. Dann brauche ich nicht mehrere Indexdateien zu öffnen.

Dies geschieht folgendermaßen: Beispiel

set index on artnr (feldname) tag "artikel" to "spstamm.cdx"
set index on liefnr (feldname) tag "liefnr" to "spstamm.cdx"
set index on lartnr (feldname) tag "lartnr" to "spstamm.cdx"

Nachher im Programm brauche ich nur nach dem use der spstamm

set index to "spstamm.cdx"
spstamm->(ordSetfocus("artikel")) oder einen anderen Tag-Namen

Somit habe ich immer gewährleistet, daß die CDX-Indexdatei aktuell ist.
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Filter für enthaltene Fields in NTX - Indexdatein

Beitrag von AUGE_OHR »

hi,
Krause hat geschrieben: OrdKey() und OrdFor() (NTX - Index)
...
welche der vorhanden Indexdateien geöffnet werden müssen
wenn du für Ordkey() oder Ordfor() Ergebnisse bekommst
wie wäre es dann mit :

Code: Alles auswählen

   cIndex := OrdName(OrdNumber()) 
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9361
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Jimmy.
so nun REPLACE mal ein FELD was zun Index N2 gehört. Nun schau dir mal die *.DBF und die *.NTX an. ALLE habe nun die selbe Uhrzeit und
nicht nur die "bearbeitet" Index.
Ja, und dann mach anschließend mal einen inhaltlichen Vergleich. Am Index hat sich nichts geändert.
Herzlich,
Tom
Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

Xbase ändert Indexfile ohne (für mich) erkennbare Logik

Beitrag von Krause »

Hi,

leider ist es so, dass Xbase die Indexdateien auch ohne sachlichen Grund (Pack, Zap, OrdKey- oder OrdFor - Bedingungsänderung etc.) und ohne (für mich) erkennbare Logik ändern kann bwz. verändert. Was geändert wird, habe ich noch nicht raus gefunden, lediglich das sich die CRC32 – Summe (nicht die Größe und schon gar nicht der sachliche Inhalt) ändert.
Falsch ist auf jeden fall, das ein abweichendes Datum (zur DBF) einen korrupten Index zur folge haben muss, ein profilaktisches Reindex führt also zu einer erhöhten (Netzwerk) Last und zu Performanzverlust. Auf der anderen Seite kann ich auch diejenigen verstehen, die auf „Nummer Sicher“ gehen.

Sensible Daten stellen wir wenn möglich, "Indexfrei" in entsprechend kleinen Datenbanken dar. Hierbei dient das Filesystem quasi als „Hierarchischen Datenmodell“ welches dem Relationalen Datenbanksystem „überlagert“ ist.

Der „selektive" Zugriff erfolgt hier zum Beispiel über (für große Datenbanken ungeeignet / zu langsam):
DbEval({|| AAdd(aArray, RecNo())}, bFor, bWhile, nCount, xRecordID, lRest)
Mit freundlichen Grüßen
Joachim Krause
Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

... packe ich alle Index in eine Indexdatei.

Beitrag von Krause »

Hallo Rolf,

du schriebst:
also nochmal wenn Datenbankeninhalte verändert werden, ändert sich auch der Index. Um Verwirrungen zu vermeiden, packe ich alle Index in eine Indexdatei. Dann brauche ich nicht mehrere Indexdateien zu öffnen.

Dies geschieht folgendermaßen: Beispiel

set index on artnr (feldname) tag "artikel" to "spstamm.cdx"
set index on liefnr (feldname) tag "liefnr" to "spstamm.cdx"
set index on lartnr (feldname) tag "lartnr" to "spstamm.cdx"

Nachher im Programm brauche ich nur nach dem use der spstamm

set index to "spstamm.cdx"
spstamm->(ordSetfocus("artikel")) oder einen anderen Tag-Namen

Somit habe ich immer gewährleistet, daß die CDX-Indexdatei aktuell ist.
Geht man in deinem Fall davon aus, das eine Nummer in der Regel ca. 10 - 18 Stellen hat (auch alphanumerische Syntax möglich) und du 3 verschieden Nummern in einem Index hältst, dann kann es schon mal passieren, das die Indexfile 25% der Größe der DBF - File überschreitet. Eigentlich erfolgt in diesem Fall der Zugriff wahrscheinlich nur über eine der drei Bedingungen und dafür „ziehst“ du die gesamte Indexfile übers Netz … würde ich nicht so machen.

Mit freundlichen Grüßen
Joachim Krause
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

RE-Alles in einer Indexdatei

Beitrag von Rolf Ramacher »

Hi Joachim,

sicherlich hast du recht das die CDX-Datei größer als die DBF ist. Aber bei uns haben unsere Kunden nur die wenigsten ein Netzwerk. Die meisten haben einen einzelnen Stand-Alone-PC.

Daher ist dies nicht so dramatisch.
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

Beitrag von Krause »

Hi,

habe mal schnell einen Filter zusammengebastelt, Basis ist eine bereits bestehende Klasse:

Code: Alles auswählen

//***********************************************************************
CLASS SYSC0303
//***********************************************************************
 EXPORTED:
 METHOD StringToArrayWithSeparateString
ENDCLASS

//***********************************************************************
METHOD SYSC0303:StringToArrayWithSeparateString(cExternDaten, cSepareteString, lNoLeerzeile)
//***********************************************************************
 LOCAL aReturnArray:=Array(0)
 LOCAL cDaten:=cExternDaten, nFound:=0, nDistanc:= 0, cString:=""

 IF ! Valtype(cDaten)=="C" .OR. cDaten==""
  RETURN Array(0)
 ENDIF

 IF lNoLeerzeile==NIL .OR. ! Valtype(lNoLeerzeile)=="L"
  lNoLeerzeile:=FALSE
 ENDIF

 nFound:=Rat(cSepareteString,cDaten)
 IF nFound = 0
  Return AClone({cDaten})
 ENDIF
 nDistanc:=LEN(cSepareteString)-1
 DO WHILE TRUE
  nFound:=At(cSepareteString,cDaten)
  IF nFound > 0
   cString:=AllTrim(SubStr(cDaten,1,(nFound-1)))
   IF lNoLeerzeile
    IF ! cString==""
     AAdd(aReturnArray,cString)
    ENDIF
   ELSE
    AAdd(aReturnArray,cString)
   ENDIF
   cDaten:=Stuff(cDaten,1,nFound + nDistanc,"")
  ELSE
   cDaten:=AllTRim(cDaten)
   IF lNoLeerzeile
    IF Len(cDaten) > 0
     AAdd(aReturnArray,cDaten)
    ENDIF
   ELSE
     AAdd(aReturnArray,cDaten)
   ENDIF
   EXIT
  ENDIF
 ENDDO
RETURN AClone(aReturnArray)
Nun die eigentliche Funktion:

Code: Alles auswählen

//***********************************************************************
FUNCTION SYS_FieldFilter(cIndexDescriptor, aDbStruct)
//***********************************************************************
 STATIC oDummy:= NIL
 IF oDummy==NIL
  oDummy:= SYSC031H():new()
 ENDIF
RETURN oDummy:FieldFilter(cIndexDescriptor, aDbStruct)


//***********************************************************************
CLASS SYSC031H FROM SYSC0303
//***********************************************************************
 EXPORTED:
 METHOD FieldFilter
ENDCLASS

//***********************************************************************
METHOD SYSC031H:FieldFilter(cIndexDescriptor, aDbStruct)
//***********************************************************************
STATIC aChar2Null:={"+","-","*","/","\","^","%","=","<",">","#","!","$","(",;
  ")","&",":","@","{","}","[","]",'"',"'",".",".T.",".F.","AND","OR","NOT","|"}
STATIC cCHRN:=CHR(0)
LOCAL iCounter:=0, aDummy:=Array(0), aReturn:=Array(0)
 FOR iCounter:=1 TO Len(aChar2Null)
  cIndexDescriptor:=StrTran(cIndexDescriptor, aChar2Null[iCounter], cCHRN)
 NEXT
 cIndexDescriptor:=UPPER(cIndexDescriptor)
 aDummy:=::StringToArrayWithSeparateString(cIndexDescriptor,cCHRN,TRUE)
 FOR iCounter:=1 TO Len(aDummy)
  IF AScan(aDbStruct,{|c| aDummy[iCounter]==c[1]}) !=0
   AAdd(aReturn,aDummy[iCounter])
  ENDIF
 NEXT
RETURN AClone(aReturn)
Der eigentliche Funktionsaufruf als Test:

Code: Alles auswählen

  ? SYS_FieldFilter(;
  "Upper(MITARBNR+MATCHCODE)+AllTrim(STR(_USRLOCK))",;
  {{"MITARBNR","C",4,0},    ; 
   {"KUNDENNR","C",4,0},    ; 
   {"WERKNUMMER","C",2,0},  ;
   {"MATCHCODE","C",8,0},   ; 
   {"EXTMATCHC","C",8,0},   ; 
   {"NUMDATTIME","N",16,0}, ;
   {"LSNUMMER","C",27,0},   ; 
   {"_USRNAME","C",4,0},    ; 
   {"_STANAME","C",15,0},   ;
   {"_USRLOCK","N",4,0}})
So, das wärs erst einmal, werde das Projekt auf jeden Fall zu Ende führen. Falls jemandem ein gravierender Fehler auffällt währe ich für ein Feedback dankbar ... :lol:

Mit freundlichen Grüßen
Joachim Krause
Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

CDX -Index immer die bessere Wahl ?

Beitrag von Krause »

Hallo Rolf,

du schriebst außerdem:
set index to "spstamm.cdx"
spstamm->(ordSetfocus("artikel")) oder einen anderen Tag-Namen
CDX - Index ist meiner Meinung nach nicht immer die bessere Wahl, bei einer Personalstammdatendatei (DBF) ist ein NTX-Index mit folgender Bedingung:

Code: Alles auswählen

UPPER(LEFT(NAME,5)+LEFT(VORNAME,5)+LEFT(ORT,5))
mindestens genauso treffsicher (bedenkt man, wie viel Müller es giebt...).

Mit freundlichen Grüßen
Joachim Krause
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15696
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hi,

da eine CDX die Texte komprimiert ablegt ist sie auf jeden Fall deutlich kleiner. Auch ist es - meiner Meinung nach - nicht richtig, dass immer die ganze Indexdatei geladen wird, solange nicht alle Datensätze der DBF gelesen werden. Xbase und Clipper ab 5.0 nutzen keine sequenziellen Indexdateien, die nur kleiner sind, sondern nutzen eine Art von Baumstruktur. Egal wie groß meine Indexe bisher waren (je etwa 20 MB bei 200 MB) und egal wie langsam das Netz war, DBSEEK() war immer sehr schnell.

Bei langsamen Leitungen (64KB) dauerte allerdings das Öffnen der DBF mit 3 bis 4 NTX Dateien einige Sekunden.

Dein Schlüsselbegriff muss nicht eindeutig sein, es gibt viele Familien, in denen Vater und Sohn den gleichen Vornamen haben und im gleichen Ort wohnen. Wenn Sie nun noch im gleichen Programm landen ;-)
Gruß
Hubert
Krause
UDF-Programmierer
UDF-Programmierer
Beiträge: 52
Registriert: Mo, 08. Jan 2007 8:55
Wohnort: In Thüringen

Möglichkeit der Datenverdichtung ...

Beitrag von Krause »

Hallo Hubert,

die Möglichkeit der Verdichtung der Daten sowie der Erhöhung der Zugriffsgeschwindigkeit über eine Baumstruktur sinkt (nicht nur) mit der anteiligen Einmaligkeit der Information, spätestens bei der Rentenversicherungsnummer dürfte da Schluss sein (außerdem gibt es die Verwaltung der Baumstruktur auch nicht ganz umsonst). Eine Personalstammdatendatenbank benötigt dann auch noch weitere Schlüssel, mindestens noch die Personalnummer (über die man dann zurückschreibt). Ein Lesezugriff mit nur einer geöffneten sinnvoll gestalteten NTX - Indexdatei dürfte da schneller sein. :?:

Um noch mal auf die Rentenversicherungsnummer zurückzukommen, innerhalb einer zu betrachtenden Menge (Unternehmen) ist die Wahrscheinlichkeit groß, das sich eine Rentenversicherungsnummer bereits bis zur vierten Stelle einmalig abbilden lässt. Hier würde der Index LEFT(RVSNR,4) völlig ausreichen, bekomme ich mehr als einen Datensatz zurück, dann wird anhand der direkt eingelesenen Daten noch einmal unterschieden (in diesem Beispiel würde der Primary Key die unternehmenseigene Personalnummer sein)

So, den Filter habe ich bei mir in der DLL eingebaut, nun muss ich noch den Rest durchprogrammieren und dann kommt noch das Schlimmtse, die Testphase. :?

Mit freundlichen Grüßen
Joachim Krause
Antworten