Als die Programmierer von Fox Software Ihre überragende Technik entwickelten, suchte man nach einem griffigen Namen für diese Neuerung. An jenem Abend lief gerade der Hitchcock-Film “Nord-Nordwest” im Fernsehen, bei dem auch der “Mount Rushmore” zu sehen war. (jener berühmte Berg mit den vier Präsidentenköpfen). Der Name Rushmore hörte sich in bezug auf Geschwindigkeit sehr gut an und schon war die Rushmoretechnologie geboren. (Es gibt auch Lästerer, die sich fragen, wie wohl der Name ausgefallen wäre, wenn Dr.Dave damals gerade den Thriller “Die Fliegen” gesehen hätte....)
Im Grunde genommen war diese Technologie nichts Neues. Lediglich die Realisierung auf einer INTEL-Plattform war das Entscheidende und somit konnte diese Technik patentiert werden. Dies war auch einer der Hauptgründe, warum Microsoft das Produkt FoxPro im Jahre 1992 für ca 79 Millionen $ aufkaufte.
Rushmore ist eine patentierte Technik zum optimierten Zugriff auf Indexdateien anstelle der Echtdaten.
Auch FoxPro kocht nur mit Wasser. Das bedeutet, daß grundsätzlich immer ein Index vorhanden sein muß, um die sagenhafte Geschwindigkeit zu erreichen. Der Aufbau eines solchen Index ist nun das “Gewusst Wie”, um Rushmore funktionieren zu lassen.
Jeder Index ist in einer CDX Datei angelegt. Es wird jedoch immer nur eine CDX Datei verwendet, um alle Indextags aufzunehmen. Die Indexe sind in komprimierter Form in einem optimierbaren B-Baum abgelegt. Allein schon die komprimierte Form verringert den Datenzugriff auf die Festplatte, was ja immer die große Bremse darstellt.
Wenn die Rushmoreengine einen bestimmten Indexausdruck sucht, baut FoxPro im Speicher eine Bitmap auf. Jeder Datensatz wird als einzelnes Bit abgebildet. Eine solche Bitmap wird für jeden Indextag aufgebaut, der in die Rushmoreoptimierung aufgenommen wird.
Nun sucht FoxPro im Index (der als Binärer Baum aufgebaut ist) nach den einzelnen Datensätzen und setzt jeweils das richtige Bit im Speicher, wenn ein Treffer gemacht wird. Dies wird für jeden benötigten Indextag gemacht.
Nun werden die Bitmaps miteinander verglichen und nur die Datensätze genommen, wo in jeder Bitmap ein Treffer gelandet wurde.
Bildlich kann man sich eine solche Bitmap wie ein Stück Papier vorstellen, wobei ein Treffer einem Nadelstich gleichkommt. Alle Papierblätter werden nun übereinander gelegt und überall, wo das Licht durchscheint, ist ein Datensatz gefunden worden, der nun verarbeitet oder angezeigt werden kann. Dies ist eigentlich der ganze Trick an der Sache.
Der Bitmap-Aufbau hat natürlich zur Folge, daß Speicherplatz für die Bitmaps benötigt wird. Für 520000 Datensätze sind ca. 64 KB notwendig. Dies ist bei den heutigen Rechnern kein Problem mehr. Zur Zeit von DOS und der Standardversion von FoxPro 2.0 war dies jedoch die Grenze, bis zu der Rushmore funktioniert, da unter DOS (ohne 386er Modus) nur 64kb große durchgängige Bitmaps aufgebaut werden konnten.
Rushmore wird automatisch bei allen Befehlen verwendet, die eine FOR-Klausel haben (Ausnahme INDEX ON .... FOR Ausdruck). Außerdem findet man Rushmore bei allen SQL-Select Befehlen und beim SET FILTER TO.
Beispiele:
Rushmore ist davon abhängig, wie die Indizes aufgebaut sind.
Ein oft beobachtetes Phänomen ist die entsetzliche Geschwindigkeit der Befehle SKIP, GO TOP und GO BOTTOM, sobald ein Filter eingesetzt wird. Dies liegt daran, daß diese Befehle keine FOR-Klausel besitzen.
Der negative Effekt tritt dann auf, wenn aus einer großen Anzahl von Datensätzen eine sehr kleine Menge an Daten herausgefiltert werden. Wenn nun durch die verbleibende Menge “geSKIPed” wird, so wird leider keine Rushmore Unterstützung eingesetzt und der nächste Datensatz wird sequentiell gesucht.
Beachten Sie, daß bereits ein SET DELETED ON einen solchen Filter setzt.
Um das Problem zu umschiffen, ist ein kleiner Trick notwendig. Als erstes benötigen wir einen Befehl, der den richtigen Datensatz findet und außerdem durch Rushmore unterstützt wird. Die Lösung ist der LOCATE-Befehl in Verbindung mit einem gesetzten Index.
Folgendes Szenario: Wir haben eine Tabelle mit Auftragsnummern. Die Auftragsnummer selbst ist unser Schlüsselbegriff “Aufnr”.
Als erstes muß die Order mit “SET ORDER TO Aufnr” eingestellt werden. Wenn nun der nächste Datensatz gesucht werden soll, so muß nur ein Index gesucht werden, der größer als der aktuelle ist.
Und schon haben wir den nächsten Datensatz gefunden. Dies ist also der Ersatz für den SKIP.
Nun fehlt noch ein Ersatz für das SKIP –1. Dies ist ebenfalls ein leichtes, wenn alleine nur die Sortierreihenfolge umgedreht wird. Man kann dies durch ein einfaches SET ORDER TO (ORDER()) DESC erledigen. Wenn Sie wieder auf “normal” umschalten wollen, genügt nun ein SET ORDER TO (ORDER()) ASCE.
Ein ähnliches Problem wie beim SKIP haben wir bei den Befehlen GO TOP und GO BOTTOM, die ebenfalls ohne Rushmore auskommen müssen. Genau so, wie beim SKIP können wir jedoch auch hier den LOCATE-Befehl verwenden.
Durch ein LOCATE FOR .T. wird durch Rushmore veranlaßt, daß der erste Datensatz gesucht wird, bei der die FOR-Bedingung ein .T. zurückliefert. Da dies nun schon beim ersten Datensatz ist, steht der Datensatzanzeiger beim ersten Datensatz. Ein wunderbarer Ersatz für GO TOP.
Anmerkung: LOCATE hat als Default bereits ein FOR .T. eingestellt, wodurch ein einfaches LOCATE ohne weitere Angaben genügt.
Es fehlt nun noch der Ersatz des GO BOTTOM Befehls. Leider funktioniert dies nicht mit LOCATE FOR .F. . Dies würde zwar den ersten Datensatz suchen, der nicht in die gefilterte Ansicht paßt, jedoch dauert dies nun wieder länger, da dieser Datensatz gesucht werden muß.
Mit SET ORDER TO (ORDER()) DESC kann die Reihenfolge wieder umgedreht werden. Nun ist ein LOCATE FOR .T. wieder erfolgreich, da in der umgekehrten Reihenfolge der erste gesucht wird, was automatisch den letzten Datensatz darstellt.
Wenn eine Datei geöffnet wird, achtet FoxPro bereits auf die Einstellung des SET DELETED Befehls. Wenn am Beginn sehr viele gelöschte Datensätze vorhanden sind, so muß sich also selbst der USE - Befehl bis zum ersten Datensatz vorkämpfen um seine internen Buffer füllen zu können.
Wenn Sie den Effekt bemerken, dann schalten Sie vor dem USE – Befehl oder vor dem DO FORM Befehl das SET DELETED auf OFF.
Mit der Einführung von Visual FoxPro 3.0, wurde ein neues Element eingeführt, das dem guten alten BROWSE sehr ähnlich ist, das GRID – Control.
Leider werden alle Controls, die als grafische Elemente instanziiert werden können nicht durch Rushmore unterstützt, so daß ebenfalls ein “SKIP – Effekt” eintritt und die Geschwindigkeit bei gefilterten Tabellen sehr verlangsamt werden kann.
Sie haben grundsätzlich zwei Möglichkeiten, um das Problem zu bewältigen. Sie können entweder zuerst einen Cursor, mit SELECT ... INTO CURSOR erstellen, oder die Datensätze mit SET KEY TO eingrenzen.
Dieser Befehl wurde uns erst seit der FoxPro für Windows Version 2.6 zur Verfügung gestellt und wurde zur Kompatibilität zu dBase 4 eingebaut.
Für diesen Befehl ist es unbedingt notwendig, daß eine Sortierreihenfolge mit “SET ORDER TO ...“ gesetzt wurde.
Nun kann der Index mit SET KEY TO eingeschränkt werden. Dies funktioniert so hervorragend schnell, daß sogar ein GO TOP und ein GO BOTTOM ohne Probleme funktioniert.
Wenn Sie sich einen Index geschickt anlegen, können Sie nahezu jedes Rushmore – Problem umgehen und haben wieder die notwendige Geschwindigkeit.
Dies ist auch die Lösung des “GRID – Problems”.
Einer der gewaltigsten Befehle unter FoxPro ist der SQL – Befehl SELECT, welcher seit der Version 5.0 auf den ANSI92 – Standard gebracht wurde. Jetzt sind auch JOINS verfügbar, welche dem SELECT – Befehl ermöglichen alle möglichen Abfragen aus einer oder mehreren Tabellen vorzunehmen.
Eine Besonderheit hat der SELECT – Befehl schon immer vorzuzeigen, da sich der Befehl nicht um geöffnete Dateien gekümmert hat und eventuell Dateien selbständig öffnen konnte. Auch ein vorher gesetzter SET FILTER Befehl wurde ignoriert und die Abfrage wurde nur auf die WHERE – Klausel beschränkt.
Seit der Version 5.0 ist sogar die SET DELETED Einstellung außer Kraft gesetzt, was jedoch in Insiderkreisen noch diskutiert wird, ob es sich dabei um ein Feature oder einen Bug handelt. Am sichersten ist es, die Abfrage auf Deleted() mit in die Where – Klausel aufzunehmen.
Ansonsten wird der SELECT – Befehl komplett von Rushmore unterstützt.
Komplett neu seit der Version 5.0 ist der SYS(3054,x). Wird der Parameter 1 mitgegeben, so wird eine Anzeige eingeschaltet, die angibt, ob eine Rushmoreunterstützte Abfrage optimierbar, teilweise optimierbar oder nicht optimierbar war.
Dies ist ein ideales Werkzeug, um seine eigene Programmierung zu überprüfen und festzustellen, ob man nicht noch ein Quentchen Geschwindigkeit aus seinen Abfragen herausholen kann.
Die undokumentierte Einstellung SYS(3054,11) schaltet auf eine Anzeige um, welche auch SELECT – Abfragen in Verbindung mit einer JOIN Anweisung anzeigen kann.
Auch für den FoxPro 2.6 Programmierer ist dies ebenfalls ein wunderbares Tool, um herauszufinden, ob alle Abfragen auch optimierbar ablaufen. Voraussetzung ist natürlich ein installiertes VFP 5.0.
Wenn Sie eine voll optimierte Abfrage starten und trotzdem eine längere Wartezeit erleben müssen, so sollten Sie einmal Ihren Index neu aufbauen, da sicherlich dort ein kleiner Fehler enthalten sein könnte.
Mit SYS(3054,0) schalten Sie die Anzeige wieder ab.
Sollten Sie einmal eine Relation zwischen zwei Tabellen benötigen, die 100% parallel laufen müssen und ohne Index arbeiten wollen, so gibt es einen einfachen Trick, der absolut “Rushmorefrei” arbeitet.
Normalerweise verwendet man für Abhängigkeiten zwischen Tabellen die SET RELATION Einstellung. Dafür ist ein Index notwendig, da ansonsten für einen Datensatz der Vatertabelle alle Datensätze der Kindtabelle durchsucht wird.
Wenn allerdings eine Relation auf die RECNO() Funktion gemacht wird, so wird FoxPro beide Tabellen absolut sicher und sagenhaft schnell miteinander synchronisieren. Dabei aber beachten, daß auf der Zieltabelle (INTO ...) wirklich kein Index gesetzt ist.
Bei jeder Abfrage haben wir die Möglichkeit einen sogenannten Scope mit anzugeben. Folgende Scopes sind möglich:
ALL | verwendet alle Datensätze zur Abfrage. |
REST | verwendet die restlichen (ab dem aktuellen Datensatz) zur Abfrage. |
NEXT | nimmt nur die nächsten x Datensätze. |
RECORD x | nimmt nur den angegeben Datensatz. |
Die Scopes ALL und REST werden von Rushmore unterstützt. NEXT und RECORD werden nicht unterstützt.
Generell werden bei Abfragen Vergleichsoperatoren verwendet. Davon sind folgende “Rushmore – optimiert”:
< | Kleiner als |
> | Größer als |
= | Gleich |
<= | Kleiner gleich |
>= | Größer gleich |
<> | Ungleich |
# | Ungleich |
== | Genau gleich |
!= | Ungleich |
ISNULL() | Ist .NULL. |
BETWEEN() | Zwischen |
INLIST() | In einer Liste von ... enthalten |
Gerell nicht optimierbar sind folgende Abfragen:
ISBLANK() | Ist Blank |
EMPTY() | Ist leer |
ISBLANK können Sie durch die Abfrage Feld = ‘ ‘ (mit einem Leerzeichen dazwischen) ersetzen.
EMPTY können Sie ebenfalls durch Feld = ‘ ‘, Feld = 0 oder Feld = {} ersetzen.
Nun wünsche ich Ihnen noch die schnellsten Abfragen, die Sie jemals gemacht haben und hoffe, Sie haben durch diesen Artikel profitiert.