2010-12-13 7 views
2

Ich habe einige Probleme zu verstehen, welche Indizes für ein Nested-Set-Modell verwendet werden. Die Abfrage ist:Nested Set Indizes & Leistung

SELECT `node`.`id`,(COUNT(parent.id) - 1) AS `depth`,`name` FROM `categories` AS `parent` 
INNER JOIN `categories` AS `node` ON (`node`.`lft` BETWEEN parent.lft AND parent.rgt) 
INNER JOIN `filebank_categories` ON (`node`.`id` = `filebank_categories`.`category_id` AND `filebank_categories`.`filebank_id` = 136) 
INNER JOIN `categories_names` ON (`categories_names`.`category_id` = `node`.`id` AND `categories_names`.`language_id` = 1) 
WHERE `node`.`system_id` = parent.system_id 
GROUP BY node.id 
ORDER BY `node`.`lft` ASC 

Diese Abfrage dauert ~ 350ms mit ~ 5000 Zeilen in categories. diese EXPLAIN gibt:

 
1 SIMPLE filebank_categories  ref  fk_filebank_categories_categories1,filebank_id   filebank_id 5 const        474 Using where; Using temporary; Using filesort 
1 SIMPLE node     eq_ref PRIMARY,lft,category,cat,lft,rgt,system,id,lft,system PRIMARY  4 filebank_categories.category_id  1  
1 SIMPLE parent     ref  lft,category,system          system  5 node.system_id      50 Using where 
1 SIMPLE categories_names  eq_ref PRIMARY,fk_categories_names_categories1     PRIMARY  8 node.id,const      1 Using where 

Tabellenstruktur:

CREATE TABLE `categories` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `system_id` int(11) DEFAULT NULL, 
    `lft` int(11) DEFAULT NULL, 
    `rgt` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `lft,category` (`lft`,`id`), 
    KEY `cat,lft,rgt` (`id`,`lft`,`rgt`), 
    KEY `system` (`system_id`), 
    CONSTRAINT `categories_ibfk_1` FOREIGN KEY (`system_id`) REFERENCES `systems` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=11519 DEFAULT CHARSET=utf8; 

Irgendwelche Ideen, wie dies zu verbessern? Ist es überhaupt möglich? Ich bin nicht sehr erfahren in Datenbank-Optimierung, so dass ich nicht wirklich herausfinden kann, welche Indizes hier verwendet werden (und warum).

Danke.

Antwort

5

Sie können versuchen, die WHERE clause zu bewegen zu verbinden, wie

SELECT ... 
INNER JOIN `categories` AS `node` ON 
(
    node.system_id=parent.system_id AND 
    node.lft BETWEEN parent.lft AND parent.rgt 
) 

und verfeinern den Index als:

CREATE TABLE `categories` (
    ... 
    KEY `system_id,lft,rgt` (`system_id`,`lft`,`rgt`), 
    ... 
); 
+1

+1 für den Index, den alten Schlüssel 'Katze, LFT, rgt' ("id", "lft", "rgt") war zum Vergleich nutzlos; Wenn Sie möchten, können Sie auch aufhören, Kommas in den Namen Ihrer Schlüssel zu verwenden - es macht das Lesen möglicher Schlüssel in Abfrageplan eine interessante Übung. – Unreason

+0

Danke! Das hilft, die Abfrage läuft jetzt in ca. ~ 100 ms. Aber ich bekomme immer noch "Verwenden von temporären; Verwenden von filesort" für die für "filebank_categories", die ich dachte, was verlangsamt alles am meisten? –

+0

filesort ist in Ordnung (der Name von filesort ist nicht so genau), die Verwendung von temporary wird durch die Gruppierung verursacht – ajreal