Hi Cheatah,
ah. MySQL kann keine Subselects, das macht die Sache etwas schwieriger.
Nicht unbedingt - je nach konkreter Ausprägung des Falls läßt sich mit JOINs bze. temporären Tabellen das meiste ziemlich gut hinkriegen.
(Ich habe selbst so eine Architektur in einer Suchmaschine.)
Nachfolgend gehe ich mal grundsätzlich auf das beschriebene Problem ein, wobei die entsprechenden Ausführungen auf Millionen von Datensätzen ausgelegt sind - bei kleinen Mengen wäre das hier Ausgeführte sicherlich Overkill. Mir geht es aber mal um's Prinzip ...
Interessant für die Beantwortung der Frage finde ich Aussagen über die Projektivität der einzelnen Felder.
Das Problem ist ja, daß ein Boolean-Feld offensichtlich genau zwei Werte enthält - ein Filter über dieses Feld liefert also im Erwartungswert die Hälfte aller Treffer der Tabelle. (Sollte ein dritter "don't know"-Wert möglich sein, ändert das nur die konkreten Werte meiner nachfolgenden Formeln, nicht aber die grundlegenden Aussagen.)
Das ist aber viel zuviel, um mit Indexbäumen noch irgend etwas zu gewinnen - der Indexzugriff ist in diesem Fall bereits wesentlich langsamer als ein ganz trivialer full table scan.
Wenn die Treffermenge einer Spalte im Schnitt nicht signifikant kleiner als 10-15% ist, dann sind Indexzugriffe nur über diese eine Spalte meistens verkehrt.
Wesentlich besser wird es, wenn ein gemeinsamer Index über sämtliche 15 Flags-Spalten verwendet wird. Denn in diesem Falle liegen größenordnungsmäßig 2^15 Index-Werte vor, und die Projektivität wird folglich ganz ausgezeichnet sein, weil der Indexzugriff nur 2^-15 der vorliegenden Daten zurück liefert. Innerhalb von 15 Vergleichen kann die Menge aller Datensätze mit exakt dieser Flag-Belegung aus beliebig vielen (!) vorliegenden Datensätzen berechnet werden - die Suchdauer ist praktisch unabhängig von der Größe des zu durchsuchenden Datenbestands.
Für die konkrete Anwendung bedeutet dies, daß eine Suche nach allen 15 Kriterien _sehr_ viel schneller sein muß als eine Suche nach nur einem Kriterium (und nebenbei auch noch viel bessere Ergebnisse liefern wird, denn die Hälfte aller Daten überflutet den Betrachter üblicherweise.
Falls es vom Inhalt der Anwendung also möglich ist, sollten die Benutzer ermutigt werden (Formular-Defaults?), möglichst viele Flags tatsächlich zu setzen - je kleiner die Treffermenge, desto schneller kann sie berechnet werden.
Schwierig wird das, wenn die Flags inhaltlich derartig sind, daß bei einigen typischerweise "don't care" durch den Anwender erwünscht oder gar notwendig ist. In diesem Falle wird der Nutzen eines Indexzugriffs wieder dramatisch einbrechen, weil bereits 5 von 15 don't cares die Treffermenge um Faktor 2^5 aufblasen und die Projektivität des Indexzugriffs entsprechend reduzieren.
Und schlimmer noch: Ein Abstieg innerhalb eines Indexbaums erfolgt sinnvollerweise durch fortgesetzte Teilung der verbleibenden potentiellen Trefferdaten. Genau das wird aber gleich ein Problem werden.
Der Indexschlüssel enthalte im vorliegenden Modell also die 15 Flags als 15 Bits (z. B. einer Integer-Zahl oder was auch immer). Ist bereits das 2. Flag in der Anforderung nicht gesetzt, dann kann der Indexzugriff an dieser Stelle nicht mehr unterteilen - er müßte parallele Suchvorgänge in mehrere Richtungen starten, und das werden die mir bekannten RDBMS-Implementierungen wahrscheinlich einfach nicht können (das ist Kristallkugel-KI - ein _sehr_ schlauer query optimizer _könnte_ begreifen, daß von den 15 Flags immerhin 14 gesetzt sind und sich das von mir beschriebene Verfahren lohnen würde ... aber wo gibt es den?).
Deshalb wäre es sinnvoll, innerhalb des Indexes die 15 Flags wenigstens in absteigender Wahrscheinlichkeit für die Nicht-Angabe durch den Anwender zu _sortieren_ - je länger der Präfix von fortlaufend gesetzten Flags sind, desto höher ist die Chance, daß ein effizienter Indexzugriff dabei zustande kommt.
Die Gefahr, daß relativ viele katastrophal schlechte Zugriffe entstehen, weil der query analyzer nicht begreift, wann ein full table scan besser wäre, ist allerdings nicht von der Hand zu weisen.
In Oracle gibt es ein zusätzliches Sprachelement namens "hints" - das sind syntaktisch gesehen Kommentare für SQL, welche aber dem query optimizer sagen können, welche Indexe er verwenden soll und ähnliches Zeug. (Jaja, wir machen von hinten durch die Brust ins Auge aus einer 4GL wieder eine 3GL, weil es Performance bringt ... ;-)
Und die PHP-Anwendung könnte durch Analyse der gesetzten Flags sehr wohl erkennen, ob eine solche Super-GAU-Anfrage vorliegt oder ob hinreichend viele Präfix-Flags gesetzt sind.
Ob aber mySQL ein Sprachmittel besitzt, um die Verwendung bestimmter Indexe zu steuern, da bin ich überfragt.
Viele Grüße
Michael
P.S.: Solange genau _ein_ Indexbaum über diese 15-Tupel existiert, wird
das Fehlen eines der "vorderen" Flags einen GAU auslösen.
Falls die entsprechenden Ressourcen verfügbar sind (inklusive der
Möglichkeit, Indexzugriffe bedingt zu formulieren), wäre es eine
enorm performance-steigernde Maßnahme, mehrere (redundante) Index-
bäume (mit verschieden angeordneten Flag-Listen) anzubieten.
Leider erfordert die _perfekte_ Lösung dann 2^15 solcher Bäume ...
das wird sich beim besten Willen nicht realisieren lassen.