IME, MySQL ne réussit pas bien à optimiser les sous-requêtes - en particulier, il ne semble pas gérer les prédicats push.
Je suis un peu confus quant à ce que la requête est réellement censée renvoyer - en particulier le "sous-parent"
Vous obtiendrez une amélioration en mettant left_id et right_id dans un seul index.
Bien que vous obteniez également une amélioration en déroulant la requête dans une procédure stockée, étant donné que vous semblez parcourir presque tout l'ensemble de données à chaque fois, une meilleure solution serait de dénormaliser la profondeur de l'arbre et de la stocker en tant qu'attribut pour chaque nœud. En effet, vous semblez le parcourir au moins deux fois dans la seule requête externe.
Cependant je remarque qu'à la fin de la requête :
HAVING depth > 0
AND depth <= 1
Ce qui est sûrement la même chose que
HAVING depth=1
Ce qui fournit alors une manière très différente d'optimiser la requête (commencez par obtenir tous les nœuds où right=left+1 pour trouver les nœuds sans enfants et pour vérifier l'identifiant de catégorie).