tengo datos jerárquicos en un modelo conjunto anidado (tabla: proyectos):MySQL: Optimización de la búsqueda de súper nodo en el árbol conjunto anidado
mi mesa (proyectos):
id, lft, rgt
1, 1, 6
2, 2, 3
3, 4, 5
4, 7, 10
5, 8, 9
6, 11, 12
7, 13, 14
...
Bastante impresa:
1
2
3
4
5
6
7
Para encontrar el nodo de súper más cercano de nodo 3 (saber su valor LFT), puedo hacer
explain
SELECT projects.*
FROM projects
WHERE 4 BETWEEN projects.lft AND projects.rgt
Lo que me da una lista de los proyectos en el camino hasta el nodo 3. Luego, al agrupar y encontrar MAX (projects.lft) de los resultados, obtengo el super nodo más cercano. Sin embargo, no puedo hacer que esta consulta se ejecute rápido, no usará los índices que he definido. EXPLICAR dice:
+----+-------------+----------+-------+----------------+----------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+----------------+----------+---------+------+------+--------------------------+
| 1 | SIMPLE | projects | index | lft,rgt,lftRgt | idLftRgt | 12 | NULL | 10 | Using where; Using index |
+----+-------------+----------+-------+----------------+----------+---------+------+------+--------------------------+
Mysql entiende lo que el índice de usar, pero todavía tiene que recorrer todos 10 filas (o 100k en mi tabla real).
¿Cómo puedo obtener MySql para optimizar esta consulta correctamente? Incluyo un script de prueba debajo.
DROP TABLE IF EXISTS projects;
CREATE TABLE projects (
id INT NOT NULL ,
lft INT NOT NULL ,
rgt INT NOT NULL ,
PRIMARY KEY (id)
) ENGINE = MYISAM ;
ALTER TABLE projects ADD INDEX lft (lft);
ALTER TABLE projects ADD INDEX rgt (rgt);
ALTER TABLE projects ADD INDEX lftRgt (lft, rgt);
ALTER TABLE projects ADD INDEX idLftRgt (id, lft, rgt);
INSERT INTO projects (id,lft,rgt) VALUES (1,1,6);
INSERT INTO projects (id,lft,rgt) VALUES (2,2,3);
INSERT INTO projects (id,lft,rgt) VALUES (3,4,5);
INSERT INTO projects (id,lft,rgt) VALUES (4,7,10);
INSERT INTO projects (id,lft,rgt) VALUES (5,8,9);
INSERT INTO projects (id,lft,rgt) VALUES (6,11,12);
INSERT INTO projects (id,lft,rgt) VALUES (7,13,14);
INSERT INTO projects (id,lft,rgt) VALUES (8,15,16);
INSERT INTO projects (id,lft,rgt) VALUES (9,17,18);
INSERT INTO projects (id,lft,rgt) VALUES (10,19,20);
explain
SELECT projects.*
FROM projects
WHERE 4 BETWEEN projects.lft AND projects.rgt
Eres mi amigo, eres un genio! Acabas de guardar nuestro servidor de DNS de la jubilación anticipada. Vas a la lista de créditos (yast.com), cuando hacemos una :) – Joernsn
Gracias :) No olvides agregar un enlace a mi blog (http://explainextended.com) :) – Quassnoi