Michael Schröpl: temporäre Tabellen

Beitrag lesen

Hi Andreas,

Aber das sind wieder 2 Dinge, Du redest glaibe ich
vom schreiben der Tabelle, was vermiutlich langsamer
ist als bei MyISAM, und ich rede vom auslesen, was
kaum merklich schneller ist.

Genau: Das Schreiben ist erheblich langsamer, wenn
dabei eine sortierte Struktur aufgebaut werden muß.
Das lohnt sich nicht, wenn nur _einmal_ auf diese
Tabelle zugegriffen werden soll - wie auch ein CREATE
INDEX für eine temporäre Tabelle sich meistens nicht
lohnt.

Siehe oben: Auch sehr viele sehr kleine Daten
brauchen zum Sortieren sehr viele sinnlose
Vergleiche.
Bei MyISAM etwas nicht? Vermutlich ist das bei
myISAM auch langsamer, so spricht nur das
schnellere Schreiben für MyISAM.

Dieses Argument bezog sich nicht auf den Tabellentyp,
sondern auf die SELECT-Query und die Reihenfolge der
Filteroperationen.

Du wirst es wissen. Ich habe das so verstanden, dass
das ein Hash ist(für mein Verständnis eine Art
Array),

Eben nicht. Ein Hash ist ein sortierter Baum, kein
linearer Array (daß PHP beides als syntaktische Syno-
nyme verwendet, verstellt Dir den Blick für die Imple-
mentierung - in Perl sind es erkennbar unterschiedliche
Konstrukte). Denn nur durch diese Sortierung ist es
anschließend möglich, sehr schnell auf die einzelnen
Elemente zuzugreifen - bei einem Array müßtest Du für
das Heraussuchen eines bestimmten Elements ja einen
full table scan machen.

Ein CREATE TABLE vom Typ HEAP muß implizit ein CREATE
INDEX bedingen, damit der HEAP wie ein Hash funktionie-
ren kann. Und _das_ sind die Kosten, die Du vermeiden
mußt, wenn Du nur ein einziges Mal auf dieses Tabelle
zugreifen willst.

Aber warum sollte man- wenn HEAP selbst ein Index
ist - einen Index über einen Index erstellen können?

Man kann für jede Tabelle beliebig viele Indexe er-
stellen - und in vielen Fällen macht das auch Sinn.

Es kann sinnvoll sein, für _jedes_ einzelne SELECT-
Statement (gemeint sind Code-Varianten, nicht Aufrufe)
einen eigenen Zugriffspfad zu bauen, wenn sich die
SELECT-Statements hinreichend stark von einander
unterscheiden.

Ein Beispiel dazu hatte ich ja schon angeführt: Ein
separater FULLTEXT-Index über die Author-Spalte, der
sehr viel schneller durchsuchbar wäre als der FULLTEXT
über die Postings selbst.
Dieser Index wäre ein optimaler Zugriffspfad für ein
Statement der Art
    SELECT * FROM postings WHERE author = MATCH (...)
_ohne_ weitere WHERE-Klauseln.
Sobald auch nur _eine_ weitere WHERE-Klausel hinzu
kommt, die einen 'besseren' Index braucht (z. B. "AND
posting_body = MATCH (...)"), ist der neue Index wert-
los, weil pro SQL-Statement nur _ein_ Index verwendet
werden kann - und zwar der beste. Das kann aber bei
verschiedenen SELECT-Statements jeweils ein anderer
sein.
Deshalb können sogar mehrere FULLTEXT-Indexe auf
derselben Tabelle Sinn machen - je nachdem, welche
SELECT-Statements Du abfeuerst.

Ich verwende den Namen "Zugriffspfad" absichtlich,
weil er die Denkweise beschreibt:
 1. Definition der Spalten (Semantik der Daten)
 2. Definition der Queries (Semantik der Auswertung)
 3. Definition der Indexe  (Tuning der Queries)
Zu jeder möglichen Variante Deines SELECT-Codes -
ausgenommen solche Queries, die sich nur durch Host-
Variablenwerte (oder solche, die eigentlich Host-Va-
riablen sein sollten, was mySQL aber wohl nicht kann)
unterscheiden, wird intern ein unterschiedlicher 3GL-
Code generiert werden, den Du wieder mit EXPLAIN prü-
fen und bei Nicht-Gefallen durch weitere Indexe auf
einen schnelleren Zugriffspfad umleiten solltest.

Es kann übrigens _noch_ krasser sein: Wenn der Query-
Optimizer intern kostenbasiert arbeitet und nicht
regelbasiert, dann kann er sogar für dasselbe SELECT-
Statement zu verschiedenen Zeiten unterschiedlichen
internen Code generieren, also unterschiedliche Zu-
griffspfade verwenden.
Stell Dir vor, FULLTEXT würde intern eine Schwarze
Liste der Worte führen und selbst _erkennen_, daß
"HTML" zu viele Treffer verursacht! Dann würde ein
MATCH gegen HTML einen _anderen_ Code generieren als
ein MATCH gegen "fsockopen" ... bei Oracle kann man in
der Konfiguration wählen, welche Strategie der Query-
Optimizer verwenden soll, und über spezielle SQL-
Erweiterungen dies sogar innerhalb jedes einzelnen
SQL-Statements verlangen ...
Ja, SQL _ist_ eine Wissen-schaft für sich. Eigentlich
will man mit einer 4GL den Programmierern verbergen,
wie ein Statement intern realisiert wird; um so schwie-
riger ist es dann leider, dies doch heraus zu bekommen,
um den schnellsten Zugriffspfad zu verwenden (oder um
zu entdecken, daß gar kein wirklich schneller Pfad
existiert, weil kein passender Index definiert wurde).
EXPLAIN ist von unschätzbarer Bedeutung, um Queries
wirklich schnell zu bekommen.

Tuning einer SQL-Anwendung ist ein bißchen ähnlich wie
das Schaffen mehrerer alternativer Navigationen auf
einer Webseite: Der eine Anwender erwartet eine Link-
Leite überall links, der andere möchte eine Sitemap
benutzen, der dritte glaubt an die Macht der Such-
maschinen ... so, wie sich diese Besucher unterschei-
den, unterscheiden sich auch Deine SELECT Statements
in ihrem Charakter.

Du sagts immer was von RAM-Disc, aber was ist das?

In UNIX gibt es keinen prinzipiellen Unterschied zwi-
schen Geräten und Dateien - alles liegt irgendwo im
Verzeichnisbaum. (Die Geräte liegen unter /dev.)

Eine RAM-Disk ist ein Gerätetreiber, der einen Puffer
im RAM in den Verzeichnisbaum einblendet. Du kannst
mit dem entsprechenden Verzeichnisbaum-Teil arbeiten
wie mit einer Festplatte, Dateien per "fopen()" öffnen
usw. - all diese Systemaufrufe werden aber von diesem
Treiber abgefangen und in seine eigenen Funktionen um-
gesetzt - wie dieser Treiber beispielsweise Seiten ein-
und auslagert, ist seine Sache, und wie die Größe sei-
nes RAM-Bereichs konfiguriert wird, das ist Sache der
Installation dieses Treibers.

Eine RAM-Disk ist aber nichts, was es nur unter UNIX
gäbe. Auch in Windows gibt es irgendwo im System-Kern
eine Adresse des Treibers für die Zugriffe auf ein
Festplattenlaufwerk. Wenn man dort an der richtigen
Stelle die Adresse durch diejenige eines residenten
eigenen Treibers ersetzt, kann man die Festplatte auch
"simulieren" - ohne daß eine Anwendung das merkt.

Sowas habe ich nicht! Geht das auch anders?

Du hast bestimmt einen RAM-Disk-Treiber in Deiner
UNIX-Kiste - im Zweifelsfalle kannst Du Dir einen aus
dem WWW fischen.
(Lesetip: http://www.linuxfocus.org/English/November1999/article124.html)

Und nein, es geht nicht anders, weil Du wahrscheinlich
nicht mySQL sagen kannst, es soll nur ganz bestimmte
Arten von Tabellen komplett im RAM halten und andere
nicht. Aber Du kannst sehr wohl bestimmte Verzeichnisse
(oder gar nur bestimmte Dateien!) Deines Pfad-Baums in
die RAM-Disk legen (via symbolic links - das wird im
mySQL-Handbuch explizit ermutigt) - mySQL wird gar
nicht merken, daß es mit einer RAM-Disk zu tun hat,
aber die Zugriffe werden entsprechend schneller.

Das einzige an Tuning was ich hier für sinnvoll
halte, ist den Anfragen-Cache(welche Variable auch
immer das sein mag) so groß wie möglich zu halten,
so dass die Anfragen nicht immer neu auf die Platte
zugreifen müseen.

Der Query-Cache bewirkt nicht, daß die Anfragen nicht
neu ausgeführt werden - er bewirkt nur, daß sie nicht
neu in mySQL-internen Code _übersetzt_ werden müssen.

Wenn Du verhindern willst, daß auf die Platte zuge-
griffen wird, dann mußt Du das in den RAM legen, worauf
zugegriffen wird - und das ist der FULLTEXT-Indexbaum.

Den Fulltext-Index selbst weiß ich auich nicht wei
ich den in den RAm bekomme, der hat ja immerhin 60
MB, aber zu besten Testzeiten hat MySQL etwas über
30 MB Ram belegt.

Suche nach dem Konfigurationsparameter für den Puffer,
der die Indexbäume aufnimmt. Dort müßten auch die
Sektoren des FULLTEXT-Index drin liegen.

Wahrscheinlich wird mySQL nie komplette Indexe im RAM
halten - aber je größer dieser Teil-Puffer ist, um so
besser ist die Cache-Hit-Rate und um so weniger
Festplattenzugriffe wirst Du brauchen.

Aber wo steht welche Parameter was genau tut?

Im mySQL-Benutzerhandbuch.

In meinem vorherigen Posting habe ich Abschnitte daraus
zitiert - Google wird Dir den URL dazu zeigen.

... mein Posting wird zu lang, ich schneide hier mal ...

Viele Grüße
      Michael