4

次の 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))

これは、約 160 万匹の動物を含むテーブルにあります。各レコードには、Animal_Id、Sire_Animal_Id、および Dam_Animal_Id (Sire = 父、Dam = 母) があります。

この sql を使用して、完全な動物の血統を表示します。結果には、動物、2 つの親、4 つの祖父母などが表示されます。

私の問題は、このステートメントが 1 匹の動物に対して 15 秒かかることです。これを最適化する方法が必要です。何かご意見は?

4

2 に答える 2

1

これをテストするのに長い時間がかからなかったので、答えには少しDYORがありますが、インラインビューを使用すると役立ちますか?

あなたは説明計画を投稿していないので、私はあまりにも多くを助けることはできません.以下の解決策では、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 )
于 2011-07-15T15:36:43.730 に答える
1

私はあなたの状況を再現しようとしましたが、Oracle にインデックスを賢く使用させることができませんでした。きっと何か賢い方法があると思います。しかし、ここで誰もそれを理解できない場合は、以下の愚かで醜い方法があります.

特定の数のレベルしか取得していないため、手動で接続を作成できます。最初のレベルを取得し、それを 2 番目のレベル (最初のクエリのコピーから結果を取得する) に結合し、それを 3 番目のレベル (2 番目のクエリのコピーから結果を取得) に結合します。ここにコピーして貼り付けて 4 番目を作成できます。元の ID が何度も繰り返されるので使いにくいですが、非常に高速です (私のマシンでは 160 万レコードで 0.005 秒です)。

--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')
);
于 2010-10-15T06:40:02.457 に答える