2011-01-16 15 views
2

Ich habe eine MySQL InnoDB-Tabelle, events, mit 3 Reihen:MySQL-Abfrage dauert länger mit Indizes?

event_id ---> int 
start  ---> long 
end  ---> long 

ich eine einfache Abfrage für alle Veranstaltungen immer innerhalb eines gewissen Bereichs geschrieben haben, dass ein Konflikt mit einem anderen Ereignis:

select a.* from events a, events b 
where a.event_id != b.event_id and 
     a.start < b.end and 
     b.start < a.end 

Der Tisch hat ~ 10K Zeilen und dauerte ~ 2 Sekunden zur Ausführung. Während ich versuchte, mit der Tabelle zu optimieren, um die Leistung zu erhöhen, fügte ich Indizes zu den Spalten start und end hinzu. Aus irgendeinem Grund verlangsamte diese Leistung dramatisch um einen Faktor von 5x. Weiß jemand, oder haben irgendwelche Ideen, warum das Hinzufügen dieser Indizes Leistung so schlecht verletzen würde?

Antwort

1

MySQL betrachtet die beteiligten Spalten und führt in die Irre, dass die Indizes helfen werden, die Abfrage zu verbessern. Das Problem besteht jedoch darin, dass die Indizes die Start-End-Abschnitte lösen, aber eine Auflösung zurück zu den Datensatz-IDs erfordern, um a.event_id! = B.event_id aufzulösen, was an sich eine teure Operation ist.

Ohne den Index erzwingt ein Cross-Join und Filter, die zwar auf eine große Anzahl von temporären Datensätzen aufsteigen kann, ist jedoch eine viel einfachere und einfachere Implementierung.

Wenn Ihre Abfrage durch einen Bereich auf a oder b gegen Start-Ende gebunden ist und/oder die Tabelle größer als 10k ist, könnte es ein ganz anderes Bild werden.

Wenn Sie den Index zu halten brauchen, können Sie die bestimmte Abfrage erzwingen (wenn Sie wissen, dass dies hilft), den Index zu ignorieren:

select a.* 
from events a ignore index (index1) 
cross join events b ignore index (index1) 
where a.event_id != b.event_id and 
     a.start < b.end and 
     b.start < a.end 

Angenommen, der Index index1 gestattet. In jedem Fall ist es immer hilfreich zu sehen, was MySQL in jedem Fall tut, indem man vor der Abfrage "EXPLAIN" hinzufügt, um zu zeigen, wie MySQL die Ergebnisse sammelt (ohne Index, mit Index, mit Index aber ignoriert)

+0

Gibt es eine Möglichkeit, die Abfrage so zu strukturieren, dass ich die Indizes behalten kann (sie werden anderen Abfragen helfen), aber immer noch den Cross-Join und Filter durchführen? – JaredC

Verwandte Themen