J'ai essayé de recréer votre situation et je n'ai pas réussi à faire en sorte qu'Oracle utilise les index à bon escient. Je suis sûr qu'il y a une façon intelligente de le faire. Mais si personne d'autre ici ne peut le comprendre, voici la manière stupide et laide.
Puisque vous n'obtenez qu'un certain nombre de niveaux, vous pouvez créer manuellement une connexion par. Obtenez le premier niveau, unissez-le au deuxième niveau (qui obtient les résultats d'une copie de la première requête), unissez-le au troisième niveau (qui obtient les résultats d'une copie de la deuxième requête), etc. Je n'ai fait que trois niveaux ici, mais vous pouvez copier et coller pour faire le quatrième. C'est plus difficile à utiliser car l'identifiant d'origine est répété tant de fois, mais c'est super rapide (0,005 seconde sur ma machine avec 1,6 million d'enregistrements.)
--Original animal
select '101' original_animal, animal_id, line_id, sire_animal_id, dam_animal_id, 0 "level" from animals where animal_id = '101'
union all
--Parents
select '101' original_animal, animal_id, line_id, sire_animal_id, dam_animal_id, 1 "level" from animals
where animal_id = (select sire_animal_id from animals where animal_id = '101')
union all
select '101' original_animal, animal_id, line_id, sire_animal_id, dam_animal_id, 1 "level" from animals
where animal_id = (select dam_animal_id from animals where animal_id = '101')
union all
--Grand parents
select '101' original_animal, animal_id, line_id, sire_animal_id, dam_animal_id, 2 "level" from animals
where animal_id =
(
select sire_animal_id from animals
where animal_id = (select sire_animal_id from animals where animal_id = '101')
)
union all
select '101' original_animal, animal_id, line_id, sire_animal_id, dam_animal_id, 2 "level" from animals
where animal_id =
(
select dam_animal_id from animals
where animal_id = (select sire_animal_id from animals where animal_id = '101')
)
union all
select '101' original_animal, animal_id, line_id, sire_animal_id, dam_animal_id, 2 "level" from animals
where animal_id =
(
select sire_animal_id from animals
where animal_id = (select dam_animal_id from animals where animal_id = '101')
)
union all
select '101' original_animal, animal_id, line_id, sire_animal_id, dam_animal_id, 2 "level" from animals
where animal_id =
(
select dam_animal_id from animals
where animal_id = (select dam_animal_id from animals where animal_id = '101')
);