2012-11-06 4 views
6

Ich habe ein ernstes Problem mit MySQL (innoDB) 5.0.Mysql Range Check anstelle von Indexnutzung auf inneren Join

Eine sehr einfache SQL-Abfrage wird mit einem sehr unerwarteten Abfrageplan ausgeführt.

Die Abfrage:

SELECT 
SQL_NO_CACHE 
mbCategory.* 

FROM 
MBCategory mbCategory 

INNER JOIN ResourcePermission as rp 
    ON rp.primKey = mbCategory.categoryId 

where mbCategory.groupId = 12345 AND mbCategory.parentCategoryId = 0 
limit 20; 

MBCategory - enthält 216.583 Zeilen

ResourcePermission - enthält 3.098.354 Zeilen.

In MBCategory habe ich mehrere Indizes (Spalten wie in Index zu bestellen):

Primary (categoryId) 
A (groupId,parentCategoryId,categoryId) 
B (groupId,parentCategoryId) 

In ResourcePermission habe ich mehrere Indizes (Spalten wie in Index zu bestellen):

Primary - on some column 
A (primKey). 

Als ich Blick in den Abfrageplan Mysql ändert die Reihenfolge der Tabellen und wählt zuerst die Zeilen aus der ResourcePermission und dann die Tabelle MBCategory (verrückte Idee) und es dauert Ewigkeiten. So habe ich STRAIGHT_JOIN das InnoDB-Engine zu zwingen richtige Tabelle Folge zu verwenden:

SELECT 

STRAIGHT_JOIN SQL_NO_CACHE 
mbCategory.* 

FROM 
MBCategory 
mbCategory 

INNER JOIN ResourcePermission as rp 
    ON rp.primKey = mbCategory.categoryId 

where mbCategory.groupId = 12345 AND mbCategory.parentCategoryId = 0 
limit 20; 

Aber hier die zweite Problem materialzie: Meiner Meinung nach mysql sollte index A (primKey) auf der Join-Operation verwenden, anstatt es durchführt Bereich für jeden Datensatz geprüft (Indexkarte: 0x400) und es dauert wieder ewig! Force-Index hilft nicht, mysql weiterhin Bereich für jeden Datensatz überprüft.

Es gibt nur 23 Zeilen in der MBCategory, die die Kriterien erfüllen, und nach der Verknüpfung gibt es nur 75 Zeilen. Wie kann ich mysql machen, um den korrekten Index für diesen Vorgang auszuwählen?

+0

Ich denke, MySQL kann nicht direkt bestimmen, wie viele Zeilen es lesen muss, um 20 übereinstimmende Zeilen zu finden; es wählt daher die größere Tabelle für 20 Übereinstimmungen aus und führt dann den inneren Join durch. Was passiert, wenn Sie das Limit entfernen? –

+0

Das Entfernen des Limits ändert nichts. Ich brauche nur mysql, um den richtigen Index zu verwenden, nicht die Bereichsprüfung –

Antwort

23

Ok, elementares Problem. Ich schulde mir ein Bier. Das System, das ich kürzlich getunnelt habe, ist kein System, das ich entwickelt habe. Ich wurde von meinem Management damit beauftragt, die Leistung zu verbessern (das ursprüngliche Team hat kein Wissen zu diesem Thema).

Nach Gebühren Wochen der Verbesserung der SQL-Abfragen, Indizes, Anzahl der SQL-Abfragen, die von der Anwendung ausgeführt werden, habe ich nicht eine der wichtigsten Dinge in diesem Fall überprüft!

SPALTENARTEN SIND UNTERSCHIEDLICH!

Entwickler, die als Art Code geschrieben haben, sollten ziemlich viel TALK bekommen.

Vielen Dank für Ihre Hilfe!

+0

Es ist erwähnenswert, dass MySQL 5.7 diese Situation verbessert, wo ein 'dynamischer Bereich' unterstützt wird. Bitte sehen Sie diesen Blog-Beitrag: http://mysqlserverteam.com/dynamic-range-access-and-recent-changes/ (die Links zu hier.) –

+1

Ich schulde dir auch ein Bier –

+1

Sehr hilfreich, danke für diesen Einblick – udog

Verwandte Themen