Wieso so langsam?

4D Server 17R6
Win Server

Suche mit ORDA in etwa so:

C_Text($such;$IndexA;$IndexB)

$such:=“A_Index = '”+$IndexA+"’"+" | A_Index = ‘"+$IndexB+"’"+" & A_ArchivNr # ‘’"

C_COLLECTION($employeesCollection)
C_OBJECT($employees)
$employeesCollection:=New collection
$employees:=ds.AquaDaten.query($such)
$employeesCollection:=$employees.toCollection()

und bekomme das:

ArchivNr suchen

grotten langsam, beim zweiten mal suchen immer noch untragbar langsam (cache wo ?)

Also ich denke da mache ich sicher etwas Falsch.

Bitte um Hilfe wo der Hund begraben ist…

Freundliche Grüsse

könnte an Ihren Daten liegen.
könnte an Ihrem Rechner liegen.
könnte an Ihrem Netzwerk liegen.
könnte an Ihrer Struktur liegen.

Raten hilft nicht wirklich.

Um zu verstehen was “hinter den Kulissen” abgeht, müssen Sie sich die Logs anschauen. Ist es die Suche oder ist es toCollection? Wieviel Daten werden in wie vielen Paketen übertragen? Ist es Bandbreite, Latenzzeit oder zuviele Daten? Oder doch die Suche?

Zum Lesen:
https://blog.4d.com/optimize-your-orda-code-with-requests-logging/

und mir mehr Details zum Anschauen:

Leider liegen nicht genügend detailierte Informationen vor
um auch nur annähernd einschätzen zu können wo der Hund begraben liegt.

So wie auch schon Herr Maul treffend anmerkte, das kann
(ohne das nähere Infos vollständig vorgelegt werden)
dann so ziehmlich an allem liegen was auf einem Rechner Probleme machen kann.

Es ist wenig sinnvoll/machbar dem Beantworter es zu überlassen
alle nur denkbaren Möglichkeiten aufzuzählen die auf einen nicht näher
eingegrenzten weitgehend individuell unbekannten Fall zutreffen könnten.
(…individuelle Einstellungen, CacheZustand, …).

Bevor ich aber viel zu weit aushohle,
gäbe es vorab noch ein paar einfache Kleinigkeiten die man überprüfen sollte
bevor man sich daran macht das ganze System nach Ursachen zu durchforsten.

Zuerst sollte man die Syntax überprüfen die im queryString geschrieben steht.
Dort sollten für stringFelder-Vergleichswerte
möglichst die geraden einfachen Hochkommata eingesetzt werden.
Für Zahlenfelder sollten Zahlenwerte und keine Hochkommata eingesetzt werden.
Natürlich vorrausgesetzt man will mit konstanten Werten vergleichen.
Auch sollte man überlegen ob man nicht lieber eine zusätzliche Klammerung verwendet
um absoltute Klarheit darüber zu geben was gruppiert UND/ODER sein soll.
Also z.B. (a=b | c=d) & x=0.
Der Beispiel-4Dcode wurde leider direkt im Forum-Editor eingefügt
ohne die Section als </> CodeSection zu markieren.
So wurden die Zeichen doppelteGeradeAnführungszeichen sowie einfacheGeradeHochkommata leidlich verstümmelt/verfälscht und man kann nicht mehr lesen ob nun der Verfasser einen SyntaxFehler gemacht hat oder ob dies nur hier im ForumEditor nachträglich verfälscht wurde.

Meine Aussage ist, das unter normalen Umständen, die vage erwähnte Beispiel-Operation
(vorrausgesetzt das Syntax+Logik korrekt geschrieben wurden)
in weit unter einer Sekunde erledigt sind incl. eines toCollection.
Selbst wenn extrem große Datenmengen+ZusätzlicheTableVerknüpfung vorlägen müsste
(soweit alles andere passt und kein Systemsonderfall vorliegt)
alles in weniger als 30sek erledigt sein.

Wie aber schon erwänt sollte man das ganze näher beschreiben,
welche Verknüpfungen gibt es,
welchen Cache hat meine DB,
ist es Einzelplatz oder Client/Server
und wenn es Client/Server ist tritt das Problem auch unter Einzelplatz auf
…usw…

Ich habe mir mal erlaubt das hier nochmal als Syntax abzubilden
mit eigenen Feldern die in meiner DB auch existieren damit ich es ausprobieren kann:

C_TEXT($such;$IndexA;$IndexB)

// [person]ID    (LONGINT)
// [person]name1 (TEXT)
// [person]name2 (TEXT)

$IndexA:="a@"  /* begin with a */
$IndexB:="b@"  /* begin with b */
  /* and ID must # 0 */

// ???QueryString:  name1 = 'a@' | (name2 = 'b@' & ID # 0)
// ???QueryString:  (name1 = 'a@' | name2 = 'b@') & ID # 0
// QueryString:  name1 = 'a@' | name2 = 'b@' & ID # 0
$such:="name1 = '"+$IndexA+"'"+" | name2 = '"+$IndexB+"'"+" & ID # 0"

C_COLLECTION($employeesCollection)
C_OBJECT($employees)
$employeesCollection:=New collection
$employees:=ds.person.query($such)
$employeesCollection:=$employees.toCollection()

Hier sind Anführungszeichen und Hochkommata unverfälscht,
nicht irgendwelches schräge Zeugs mit schrägesHochkommata oder schrägesAnführungszeichen
das sind Zeichen für MenschenTexte und nicht exakt das Zeichen was man in Codes stets immer zu verwenden hat, also geradesEinfachesHochkommata oder geradesDoppeltesAnführungszeichen.

Noch niemals habe ich es geschaft das eine solche query+toCollection
mehr wie ein paar Sekunden braucht bei Datensatzmengen von kleiner 500Tausend
und dies natürlich mit sowohl auch ohne Index.

Manchmal hilft es auch den MaintainenceSecCenter zu bemühen
und dort mindestens repair all indexes auszuführen.
Das sind aber dann exotische Ausnahmefälle wo konkret was in Schieflage geraten ist.

etwas viel könnte…
Grundsätzlich gibt es mit dieser Datenbank keine Performance-Probleme.
Es ist ein erster Versuch mit ORDA und ich bin nicht gefasst gewesen, dass so ein gewaltiger Unterschied von der Einplatz zur Client Server Version möglich ist.
Einplatz “traditionell” 31 millisec ORDA 156 millisec für’s gleiche Ergebnis.
Mehrplatz ORDA mehrere lange Sekunden (im Moment nicht gemessen, nur gefühlt)

Da uns kein zip einer Beispiel-DB zu verifizieren vorliegt
kann man viel rätseln.

Ein gutes immer gültiges Rezept ist, eingrenzen, eingrenzen und eingrenzen,
solange bis man den Verursacher eindeutig greifen/verifizieren kann.
Sowas bedarf immer Test und Gegentest, positiv vs. negativ,
also mit Verursacher passiert es immer und
ohne dem Verursacher in vergleichbarer Situation passiert es dann immer NICHT mehr!
(und das geht nur mit dem Original wo das Problem auch auftritt)
(in meinen DBs ich bisher noch keine Wartezeiten verifizieren, auch nicht mit vielen Records)

Was passiert mit exakt der selben DB und Codezeilen (insbesondere .toCollection)

  • wenn man sie auf v18, v18R2 und v18R3 ausführt
  • was passiert genau wenn man gleiches Bsp. am Einzelplatz(Local) ausführt
  • was passiert wenn man .toCollection(filter) verwendet
    und testet indem man unterschiedliche Felder ausschliesst.
    Was ist/sind die Felder(eigenerTable und relationTables)
    die das ganze so abnorm langsam machen?
    Gibt es ggf. ExtremLangeTextfelder, Blobs oder Bilder welche ausserhalb des Tables
    gespeichert werden.
    Mit Filter eingrenzen welches die Felder sind die
    dieser abnormer Zeit bedürfen um ihre Werte in eine Collection zu übertragen.

So ein Foto kann auch helfen das andere ungefähr sehen können
was eigentlich genau für ein Sonderfall vorliegt.
Natürlich ist es immer möglich das ein generelles Problem anliegt,
aber das kann man erst sagen wenn man alle möglichen eigenen Fehler
zweifelsfrei ausgeschlossen hat
oder andere in anderen DBs ähnliches verifizieren können
und ggf auch noch sagen können, das passiert mit gleicher DB+Code immer in v17
und in v18 plötzlich generell nie mehr.

Danke für die Ausführliche Antwort.

Ich weiss nicht ob es am queryString liegt, es kommt auf jeden Fall das richtige Suchergebnis.
Wie ist denn die richtig Syntax zur Suche auf alle Datensätze bei denen das A_ArchivNr (Text) leer ist?

…versuch weiter zu testen auch mit V18

egal. Request Log verwenden und dadurch eindeutig erkennen welcher Befehl wie lange benötigt.

Wenn es der Query ist, Query Path abfragen und dadurch eindeutig erkennen welche Teiloperation lange dauert. Dann kann man eine exakte Frage stellen (falls überhaupt noch nötig und man eh nicht gleich “ach so…” Erlebnis hat.

könnte auch an der Blindheit des Anwenders liegen…

$employeesCollection:=$employees.toCollection()
schiebt die ganzen Daten in die Collection (kein Wunder dass das Zeit braucht)
$employeesCollection:=$employees.toCollection(“A_ArchivNr”)
schieb nur die Daten die ich auch wirklich gebrauche in die Collection
und schon ist die Welt wieder in Ordnung.

Danke für die Hilfe und sorry für die Aufregung

1 Like

Wenn …NR ein Textfeld ist dann ist queryString soweit in etwa richtig,
leider ist aber in deinem ersten Post dein Beispiel-Code vom Forum-Editor
verhexelt worden, und so kann ich nicht erkennen ob dein echter Code
irgendeiner dieser falschen Zeichen drin hat statt der geradenDoppeltenAnführungszeichen
und dem geradenEinfachenHochkommata.
Im Normalfall meistens würde dann eine Fehlermeldung kommen das queryString
unzulässige Syntax enthält.
Ich würde mich aber nicht darauf verlassen, sondern selbst dafür Sorge tragen
das meine zentrales Testbeispiel keine Tippfehler/Autoübersetzerfehler enthält.
(sorry wenn ich das so ausbreite aber immer dann wenn ich vorraussetze das jedem bekannt ist das es hier um Zeichencodes geht und nicht um etwas was in etwa von der Ferne so aussieht wie ein Anführungszeichen aber eben ein aderer Zeichencode ist, dann kommt ein Fall wo genau das übersehen wurde).
(auch hoffe ich das einfach mal auszuprobieren, copy&paste des eigenenCodes der hier im ersten Forum-Beitrag abgebildet ist in den Methodeditor der sofort deutlich zumindest ein paar der schrägenZeichen reklamiert, womit dann auch klarer würde warum ich das aufgezeigt habe).
Ein Foto des Inhaltes von $such im Debugger würde mir zumindest einwenig Klarheit verschaffen.
Sowie auch ein Foto vom Inhalt von $employees mir einwenig zeigen würde was den eigentlich für Inhalte mit toCollection übertragen werden (Anzahl gesamt und auch Details zum 1.Datensatz).
Lt. dem Foto mit der Ablaufanzeige ist eher zu vermuten es passiert bei toCollection,
kann aber ebenso indirekt mit dem Query oder RelatedTables zusammenhängen.
Wenn nur eine AutoRelation nicht stimmt dann kann es passieren das man zu einem Datensatz
sämtliche Datensätze einer relTable bekommt und wenn die 1Mio Records und 200Felder hat mit großen Inhalten, dann dauert die Übertragung in toCollection natürlich ewig. Beispiel Autorelation zu VieleTabelle hat einen Key=0 und zufällig haben 90% der Records der vieleTabelle versehentlich eine 0 im Key (longint ohne Angabe). Gibt es überhaupt in deinem Fall aktive AutoRelTables, das sieht man im Ergebnis im Debugger wenn man $employees ansieht nach der query.

Dies ist eine korrekte Suche nach Textfeld=Leer:

$such:="A_ArchivNr = ''"

kann natürlich mit AND sowie OR kombiniert werden:

$such:="(A_Index = 'testX' OR A_Index = 'testY') AND A_ArchivNr # ''"

natürlich gibt es etliche alternative Schreibweisen (ich möchte hier nicht alle aufzählen müssen)

$such:="(A_Index = 'testX' | A_Index = 'testY') & A_ArchivNr # ''"

$such:="(A_Index = :1 | A_Index = :2) & A_ArchivNr # ''"

Ich würde mir hier eine funktionierende Schreibweise aussuchen,
und nicht unnötig die Problemursache verschleiern
indem man umbedingt ausprobieren möchte ob das auch ohne Klammern
und ggf. ohne meine gezeigten Leerzeichen geht.
Es geht ja jetzt nicht darum was für alternative Schreibweisen bis genau wohin noch
gültig sind, sondern darum eine gültige Schreibweise zu haben die sicher
dann auszuschliessen ist das es daran liegt das man nur queryString falsch geschrieben hat.
https://doc.4d.com/4Dv18R3/4D/18-R3/dataClassquery.305-4900853.en.html

Hallo Herr Veith
Dank Ihrer ausführlichen Antwort ist mir die verknüpfte Suche nun klarer.
Das Problem war aber wie schon erwähnt das .toCollection()
Die Tabelle enthält relativ viele Felder und vor allem ein paar Textfelder mit sehr viel Text.
.toCollection(“A_ArchivNr”) hat geholfen…