Я попытался воссоздать вашу ситуацию и не смог заставить Oracle разумно использовать индексы.Я уверен, что есть какой-то умный способ сделать это.Но если никто здесь не может понять это, ниже приведен тупой, безобразный способ.
Поскольку вы получаете только определенное количество уровней, вы можете вручную создать соединение с помощью.Получить первый уровень, объединить это на второй уровень (который получает результаты от копии первого запроса), объединить это на третий уровень (который получает результаты от копии второго запроса) и т. Д. Я сделал только три уровняздесь, но вы можете скопировать и вставить, чтобы сделать четвертый.Его сложнее использовать, поскольку исходный идентификатор повторяется очень много раз, но он очень быстрый (0,005 секунды на моей машине с 1,6 миллионами записей).
--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')
);