Frage

Sind die folgenden Abfragen effektiv in MySQL:

SELECT * FROM table WHERE field & number = number; 
# to find values with superset of number's bits

SELECT * FROM table WHERE field | number = number; 
# to find values with subset of number's bits

... wenn ein Index für das Feld erstellt wird?

Wenn nicht, gibt es eine Möglichkeit, es zu machen, schneller laufen?

War es hilfreich?

Lösung

Update:

Sehen Sie diesen Eintrag in meinem Blog für Leistungsdetails:


SELECT * FROM table WHERE field & number = number

SELECT * FROM table WHERE field | number = number

Dieser Index kann auf zwei Arten wirksam sein:

  1. frühe Tabellen-Scans zu vermeiden (da der Wert zum Vergleich im Index selbst enthalten ist)
    • Um den Wertebereich geprüft zu begrenzen.

Weder Zustand in den Abfragen oben ist sargable , das ist der Index nicht für den Bereich Scan verwendet wird (mit den Bedingungen, wie sie jetzt sind).

Allerdings Punkt 1 hält nach wie vor, und der Index kann nützlich sein.

Wenn Ihre Tabelle enthält, sagt sie, 100 Bytes pro Zeile im Durchschnitt und 1,000,000 Aufzeichnungen, dann wird die Tabellen-Scan müssen 100 Mb von Daten scannen.

Wenn Sie einen Index (mit einem 4-Byte-Schlüssel, 6-Byte-Zeilenzeigern und einigen internen Overhead) haben, wird die Abfrage benötigt nur 10 Mb von Daten und einige zusätzlicher Daten aus der Tabelle zu scannen, wenn die Filter erfolgreich ist.

  • Die Tabelle Scan ist effizienter, wenn Ihr Zustand nicht selektiv ist (Sie haben eine hohe probablility die Bedingung entsprechen).
  • Der Index-Scan effizienter ist, wenn Ihr Zustand selektiv ist (Sie haben niedrigen probablility die Bedingung entsprechen).

Diese beiden Abfragen erfordern den ganzen Index zu scannen.

Aber durch die AND Abfrage Umschreiben Sie aus dem Bereich auf dem Index profitieren.

Diese Bedingung:

field & number = number

können nur die Felder übereinstimmen, wenn die höchsten Bits von number Satz zu im field eingestellt sind.

Und Sie sollten nur diese zusätzliche Bedingung zur Verfügung stellen, um die Abfrage:

SELECT  *
FROM    table
WHERE   field & number = number
        AND field >= 0xFFFFFFFF & ~((2 << FLOOR(LOG(2, 0xFFFFFFFF & ~number))) - 1)

Damit wird der Bereich für die Grobfilterung und die Bedingung für die Feinfilterung verwendet werden.

Je mehr Bits für number ungesetzt sind am Ende, desto besser.

Andere Tipps

Ich bezweifle, dass der Optimierer, dass eine Figur würde ...

Vielleicht können Sie auf diese Fragen rufen EXPLAIN und meine pessimistischen Vermutung bestätigen. (Erinnern natürlich, dass viel von Abfrageplan Entscheidungen basieren auf der spezifischen Instanz einer bestimmte Datenbank, das heißt die variable Mengen von Daten und / Erz lediglich Daten mit einem anderen statistischen Profil kann verschiedene Pläne erzeugen).

Unter der Annahme, dass die Tabelle eine erhebliche Menge von Zeilen hat, und daß die „bitwised“ Kriterien bleiben selektiv genug) eine mögliche Optimierung wird erreicht, wenn eine bitweise Operation auf jeder einzelnen Zeile zu vermeiden, indem die Abfrage mit einem IN-Konstrukt Neuschreiben (oder mit einem JOIN)

So etwas (konzeptuelle, das heißt nicht getestet)

CREATE TEMPORARY TABLE tblFieldValues
  (Field INT);

INSERT INTO tblFieldValues
   SELECT DISTINCT Field
   FROM table;

-- SELECT * FROM table WHERE field | number = number; 
-- now becomes
SELECT * 
FROM table t
WHERE field IN 
    (SELECT Field 
     FROM tblFieldValues 
     WHERE field | number = number); 

Der volle Nutzen eines Ansatz wie dieser Bedarf mit unterschiedlichen Anwendungsfällen (von denen alle mit einer beträchtlichen Anzahl von Zeilen in der Tabelle, da sonst der direkte „WHERE Feld | number = Zahl“ -Ansatz effizient genug ist) ausgewertet werden, aber ich vermute, dies deutlich schneller sein könnte. Weitere Gewinne erzielt werden, wenn die „tblFieldValues“ muss nicht jedes Mal neu erstellt werden. Effiziente Erstellung dieser Tabelle natürlich impliziert einen Index auf Feld in der ursprünglichen Tabelle.

Ich habe das selber ausprobiert, und die bitweise Operationen sind nicht genug Mysql verwenden, einen Index für die Spalte „Feld“ zu verhindern. Es ist wahrscheinlich, aber, dass ein Scan des Index stattfindet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top