简体   繁体   English

Oracle 10g按优先级连接 - 性能问题

[英]Oracle 10g Connect By Prior - Performance Issues

I have the following SQL statement: 我有以下SQL语句:

SELECT 
    CONNECT_BY_ROOT ANIMAL_ID "ORIGINAL_ANIMAL" ,
    ANIMAL_ID, LINE_ID, SIRE_ANIMAL_ID, DAM_ANIMAL_ID,
    LEVEL -1 "LEVEL" FROM ANIMALS 
START WITH ANIMAL_ID IN( '2360000002558' )
CONNECT BY
  ((PRIOR SIRE_ANIMAL_ID = ANIMAL_ID and LEVEL < 5) OR (PRIOR DAM_ANIMAL_ID = ANIMAL_ID AND LEVEL < 5))

This in in a table with about 1.6 Million animals. 这张桌子上有大约160万只动物。 Each record has Animal_Id, Sire_Animal_Id, and Dam_Animal_Id (Sire = Father, Dam = Mother). 每条记录都有Animal_Id,Sire_Animal_Id和Dam_Animal_Id(Sire =父亲,Dam =母亲)。

I use this sql to display the full animal pedigree. 我使用这个sql来显示完整的动物血统。 Results Will show Animal, 2 Parent, 4 GrandParents, etc. 结果将显示Animal,2 Parent,4 GrandParents等。

My issue is that this statement takes 15 seconds, for one animal. 我的问题是,对于一只动物,这个陈述需要15秒。 There has got to be a way to optimize this. 必须有一种方法来优化这一点。 Any thoughts? 有什么想法吗?

I tried recreating your situation and I wasn't able to get Oracle to use the indexes wisely. 我尝试重新创建你的情况,我无法让Oracle明智地使用这些索引。 I'm sure there's some smart way to do it. 我确信有一些聪明的方法可以做到这一点。 But if no one else here can figure it out, below is the dumb, ugly way. 但如果这里没有其他人可以弄清楚,下面是愚蠢,丑陋的方式。

Since you're only getting a certain number of levels you can manually create a connect by. 由于您只获得了一定数量的级别,因此您可以手动创建连接。 Get the first level, union that to the second level (which gets results from a copy of the first query), union that to the third level (which gets results from a copy of the second query), etc. I only did three levels here, but you can copy and paste to make the fourth. 获得第一级,第二级联合(从第一个查询的副本获得结果),联合到第三级(从第二个查询的副本获得结果)等等。我只做了三个级别在这里,但您可以复制并粘贴以制作第四个。 It's harder to use since the original id is repeated so many times, but it's super fast (0.005 seconds on my machine with 1.6 million records.) 由于原始id重复了很多次,所以使用起来比较困难,但速度非常快(我的机器上有0.005秒,有160万条记录。)

--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')
);

I haven't had a long time to test this so there is a bit of DYOR in the answer but would using an inline view help? 我没有很长时间来测试这个,所以答案中有一点DYOR但会使用内联视图帮助吗?

As you haven't posted an explain plan I can't help too much i'm afraid and in the solution below, you may find that the union in the WITH clause causes you performance issues but it might help you on your way to a solution. 由于你还没有发布解释计划,我不能太担心,在下面的解决方案中,您可能会发现WITH子句中的联合会导致性能问题,但它可能会帮助您前往解。

WITH ani
  AS (SELECT animal_id, 
             line_id, 
             sire_animal_id, 
             dam_animal_id, 
             sire_animal_id AS generic_id
        FROM animals
      UNION
      SELECT animal_id, 
             line_id, 
             sire_animal_id, 
             dam_animal_id, 
             dam_animal_id AS generic_id
        FROM animals)
SELECT CONNECT_BY_ROOT animal_id "ORIGINAL_ANIMAL",
       animal_id,
       line_id,
       sire_animal_id,
       dam_animal_id,
       LEVEL - 1 "LEVEL"
  FROM ani
 START WITH animal_id = '2360000002558'
 CONNECT BY (PRIOR generic_id = animal_id AND LEVEL < 5 )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM