Warum verwendet MySQL keinen Index für einen Vergleich größer als?

8

Ich versuche eine größere Abfrage zu optimieren und stolperte in diese Wand, als ich feststellte, dass dieser Teil der Abfrage einen vollständigen Tabellenscan durchführte, was meiner Ansicht nach keinen Sinn ergibt, wenn man bedenkt, dass das fragliche Feld ein Primärschlüssel ist. Ich würde annehmen , dass der MySQL Optimizer den Index verwenden würde.

Hier ist die Tabelle:

%Vor%

Diese einfache Abfrage scheint einen vollständigen Tabellenscan durchzuführen:

%Vor%

Dies ist die Ausgabe des EXPLAIN:

%Vor%

Gibt es Ideen, wie Sie verhindern können, dass diese einfache Abfrage einen vollständigen Tabellenscan durchführt? Oder habe ich kein Glück?

    
Robin 14.01.2011, 13:58
quelle

5 Antworten

13

MyISAM -Tabellen sind nicht gruppiert, ein PRIMARY KEY -Index ist ein sekundärer Index und erfordert eine zusätzliche Tabellensuche, um die anderen Werte zu erhalten.

Es ist mehrere Male teurer, den Index zu durchlaufen und die Lookups durchzuführen. Wenn Ihre Bedingung nicht sehr selektiv ist (ergibt einen großen Anteil an den gesamten Datensätzen), wird MySQL den Tabellen-Scan günstiger betrachten.

Um zu verhindern, dass ein Tabellenscan durchgeführt wird, könnten Sie einen Hinweis hinzufügen:

%Vor%

, obwohl es nicht unbedingt effizienter wäre.

    
Quassnoi 14.01.2011, 14:03
quelle
11

Es wäre wahrscheinlich besser, MySql den Abfrageplan zu überlassen. Es gibt ein gutes die Wahrscheinlichkeit, dass ein Index-Scan weniger effizient ist als ein vollständiger Table-Scan.

Es gibt zwei Datenstrukturen auf der Festplatte für diese Tabelle

  1. Der Tisch selbst; und
  2. Der Primärschlüssel B-Tree-Index.

Wenn Sie eine Abfrage ausführen, verfügt das Optimierungsprogramm über zwei Optionen für den Zugriff auf die Daten:

SELECT * FROM userapplication WHERE application_id > 1025;

Verwenden des Index

  1. Durchsuchen Sie den B-Tree-Index, um die Adresse aller Zeilen mit application_id > 1025 zu finden.
  2. Lesen Sie die entsprechenden Seiten der Tabelle, um die Daten für diese Zeilen zu erhalten.

Den Index nicht verwenden

Durchsuchen Sie die gesamte Tabelle und wählen Sie die entsprechenden Datensätze aus.

Auswahl der besten Strategie

Der Job des Abfrageoptimierers besteht darin, die effizienteste Strategie zum Abrufen der gewünschten Daten auszuwählen. Wenn es viele Zeilen mit einem application_id > 1025 gibt, kann es tatsächlich weniger effizient sein, den Index zu verwenden. Wenn zum Beispiel 90% der Datensätze ein application_id > 1025 haben, müsste der Abfrageoptimierer ungefähr 90% der Blattknoten des b-Baum-Index scannen und dann mindestens 90% der Tabelle lesen, um das tatsächliche zu erhalten Daten; Dies würde bedeuten, dass mehr Daten von der Festplatte gelesen werden müssen, als nur die Tabelle zu scannen.

    
Andy Skirrow 14.01.2011 14:20
quelle
1

Mysql hält einen vollständigen Tabellenscan definitiv für günstiger als den Index; Sie können jedoch die Verwendung Ihres Primärschlüssels als bevorzugten Index mit:

erzwingen %Vor%

Beachten Sie, dass mysql mit "USE INDEX" anstelle von "FORCE INDEX" nur einen Hinweis auf mysql für den zu verwendenden Index vorgibt, weiterhin einen vollständigen Tabellenscan:

%Vor%     
ᴳᵁᴵᴰᴼ 14.01.2011 14:24
quelle
0

Wenn Ihr WHERE ein Vergleich "größer als" ist, gibt es wahrscheinlich einige Einträge zurück (und kann realistisch alle zurückgeben), daher werden in der Regel vollständige Tabellen-Scans bevorzugt.

    
Kajetan Abt 14.01.2011 14:08
quelle
-5

Es sollte der Fall sein, nur zu tippen:

%Vor%

Wie unter dieser Link beschrieben. Gemäß dieser Anleitung sollte es funktionieren, wo die Anwendungs-ID ein numerischer Wert ist, für nicht-numerische Werte sollten Sie Folgendes eingeben:

%Vor%

Ich glaube nicht, dass irgendetwas mit Ihrem SELECT falsch ist, vielleicht ist es ein Problem mit der Tabellenkonfiguration?

    
Dan Hanly 14.01.2011 14:02
quelle

Tags und Links