[mysql] wie wird ne Bedingung abgearbeitet?

Bububoomt

ohne Vertrauen
ID: 10361
L
28 April 2006
19.666
769
Also ich frage mich gerade wie wird bei mysql eine Bedingung behandelt.

Wenn ich jetzt eine kompliziertere Bedingung nutze, in der ich etwas berechne, wie wird das abgearbeitet?

Also wenn ich z.b. sowas habe:

where x>20000 and x<30000 and y>10000 and y<20000 and (sqrt(pow(x,2)+pow(y,2))> 28000)

Wird die berechnung nur auf die Zeilen begrenzt, die die ersten 4 bedingungen erfüllen, oder wirds auf alle ausgeführt?

Also wird ein & oder ein && durchgeführt?

Habe beim google nichts gefunden.
 
Ohne jetzt Ahnung zu haben, ob der MySQL-Optimierer zusätzliche Schritte (z.B. Berechnungen erst am Ende machen) macht, so kann ich dir sagen, dass man sich bei AND- und OR-Ausdrücken immer folgende Gesetze zu Nutze macht:
a & 0 = 0, a∈{0, 1}
a | 1 = 1, a∈{0, 1}​
bzw
a && false = false, a Prädikat
a || true = true, a Prädikat
.

Wertet also jemand einen AND-Ausdruck aus, so wird er schon mit dem Ergebnis false abbrechen, sobald er den ersten Term gefunden hat, der false ist (Für OR-Ausdrücke analog beim ersten true-Term).

Für genauere Infos warte einfach, bis ice-breaker den Thread gewittert hat :mrgreen:
 
Ok, mal gucken was er sagt.

Ich kann mir auch nie merken ob bei & oder bei && nach einem false abgebrochen wird.
 
Ich kann mir auch nie merken ob bei & oder bei && nach einem false abgebrochen wird.
Ich käme nie auf die Idee, so zu unterscheiden.

& = bitweises Und
&& = logisches Und

Dass nur bei einem der beiden abgebrochen wird, wüsste ich nicht. Man sollte sowieso niemals ein bitweises Und verwenden, um ein logisches Und darzustellen.
Vermutlich "funktioniert" es deshalb anders.
 
Ja wissen viele nicht, das es da den unterschied gibt ;)

PHP:
$a=false;
$b=0;
if($a & ++$b==1)
;
echo $b
-> 1

PHP:
$a=false;
$b=0;
if($a && ++$b==1)
;
echo $b

-> 0

Braucht man eher selten, aber gibt schon mal komische konstellationen wo es halt Sinn macht.

Also bei & wird auf jedenfall auch dre rechte Ausdruck ausgeführt/überprüft, bei && nur wenn der linke Teil true ist.

Eben mal getestet.
 
Für genauere Infos warte einfach, bis ice-breaker den Thread gewittert hat :mrgreen:
muhahaha :ugly:


Also das Verhalten, was du erfahren möchtest ist ein relativ komplexes, denn das erfordert ein Verständnis von Bäumen und wie MySQL mit diesen Index-Bäumen umgeht.
Ich kann dir da nur nen Einblick geben und nicht alles erklären, aber ich gebe mein bestes.:

Also zu erstmal ist dein Query nicht "trivial". Nur mit den ersten 4 Bedingungen könnte der MySQL-QueryOptimizer den Query einfach als "Index-Query" definieren, da er nur nach den Bedingungen schauen muss.
Deine 5. Bedingung ist nicht mehr mit einem Index lösbar, da du Berechnungen ausführst, die ein Index nicht vorgespeichert hat (dein Pythagoras Dreieck) müsste MySQL - würde es nur diese eine Bedingung bekommen - einen Full-Table-Scan ausführen, und jede Zeile deiner Datenbank mit diesen Berechnungen prüfen, im Gegensatz zu den ersten 4 Bedingungen bei denen er nur im Index nachschauen muss.
Wie MySQL in diesem genauen Fall entscheidet kann ich dir nicht versprechen, ich nehme aber an, wie theHacker es auch schon beschrieb, dass er erst die ersten 4 Bedingungen nutzt und auf die Datensätze auf die die ersten 4 Bedingungen zutreffen, deine 5. Bedingung anwenden wird (Ein Explain wird es dir sagen, du musst nach einem "Use index" schauen).

Ich kann dir aber noch einen Tipp zur Optimierung auf den Weg geben:
Ich nehme mal an, du hast einen Index für x und einen für y definiert gell? MySQL wird deinen Query dann so aufteilen, dass er den Index nutzt und alle Zeilen selected, die auf die 1. und 2. Bedingung zutreffen (x-Index), eine Abfrage mit dem Index Y machen (3. und 4. Bedingung nutzen), dass dann mit einem Union vereinen und darauf wiederum die 5. Bedingung anwenden.
Aber eigentlich ist es ja nicht das, was du möchtest, denn es sollen ja Zeilen selected werden auf die die ersten 4 Bedingungen zutreffen, also warum muss er den aufteilen?
Ganz einfach: MySQL kann pro Query nur einen Index nutzen. Also entscheidet es sich jeweils für den Index X oder Y und lädt deren Datensätze und merged sie mit Union. Jedoch können das ziemlich viele sein, nämlich 20.000 (10 für X und 10 für Y) das liegt wahrscheinlich nicht ganz in deinem Interesse.
Der Trick ist einen so genannten "geteilten Index" zu erstellen. Du sagst damit dass du einen Index auf X, Y erstellst, das bedeutet dann, er indexiert die Spalte X und für jeden Wert der Spalte X kann er dann noch einen Index für Y nutzen (in Abhängigkeit von X). Jedoch kann nur Y nicht mit diesem abgedeckt werden (lies dazu am besten mal das MySQL-Manual über "partielle Indexe" befragen). Dadurch kannst du deine Menge an Ergebnisdatensätzen, die MySQL laden muss um die 5. Bedingung zu prüfen drastisch reduzieren, was den Query deutlich schneller macht und zudem weniger Speicher verbraucht.

Ich hatte eigentlich gar nicht vor so nen Roman zu schreiben :biggrin:

Tut mir leid, dass da nun keine Beispiele oder so zur Erklärung drinne sind, der Stoff ist recht komplex und wäre damit besser zu verstehen, aber mit Beispielen würde ich Stunden dafür brauchen. Hmm, sollte ich vllt mal anfangen zu bloggen? :ugly:
 
Hmm, alsonicht so ganz einfach, wohl gemerkt die abfrage ist noch recht trivial, was ich wohl vorhaben werde, wird komplizierter, wobei ich noch gar nicht weiß wie ichs machen muß/werde.

Also es geht um folgendes:
ich habe eine tabelle in der ein start und endpunkt (P1 x1/y1 und P2 x2/y2) vorhanden ist, die eine Gerade ja bilden, länge der Geraden habe ich.

nun möchte ich wissen, ob im Radius r von Punkt P3 x3/y3 ausgehend eine gerade vorhanden ist. Also will alle Geraden die näher als r am punkt P3 dran sind.

Wie die Berechnung durchzuführen ist muß ich mir auch noch ausdenken...

Geht halt darum, die Menge auf die die Berechnung dann angewendet wird möglichst zu minimieren.
 
ich habe zwar nun nur nen Bruchteil verstanden (kann es gerade net ganz so anchvollziehen) aber das wird ne recht heftige Aufgabe ;)
Unbedingt schauen ob du irgendwo "precalculated Values" nutzen kannst, also Daten schon in der Datenbank fertig berechnet zwischenspeichern.

Wird das ne Umkreissuche ?
 
Mal ne ganz andere Sache:
Brauchst du das häufiger? Koordinaten und Euklidische Norm hört sich ja so an.

Du könntest natürlich die Euklidische Norm als Spalte in der Tabelle mitführen und damit MySQL bei der Abfrage die Rechnerei abnehmen. Ob sich das rentiert, kommt aber wohl auf die Anzahl der Datensätze und das Verhältnis von INSERT/UPDATE zu SELECT an.

edit@über mir:
Ja, die Idee hatte ich doch auch :doh: :biggrin:

edit2:
Wird das ne Umkreissuche ?
Klingt eher nach Mindestangriffsradius :think:
 
Zuletzt bearbeitet:
@ Hacker,
genau daran habe ich nun auch gedacht, das man das für sowas für mich sinnvoll gebrauchen könnte. Aber ist nciht für ein Spiel.

Mir fällt da noch ne bessere ein :p
MySQL besitzt seit der Version die sogenannten GIS-Funktionen, für effiziente Speicherung und Berechnung von geographischem Zeug.
Vllt ist da mittlerweile was in seine Richtung schon dafür implementiert worden.

Du kommst dem verdammt nahe ;)
Ist fürs Studium (Geraden=Leitungen).
Habe zwar momentan im Praxissemester viel mit Koordinaten zu tun (geom, UTM, Gauskrüger...) aber leider dieses Problem so nicht.

MYsql hat auch inzwischen die funktionen? dann muß ich mal gucken ob ich die nutzen kann und ob ich damit weiter komme.

das schlimmste ist ich muß es zudem in db4o (bzw. irgend einer objektorintierten db) nochmal "nachbauen".