2016-07-17 6 views
1

私は2つのテーブルを持っています。 1つは空で、もう1つは約2万レコードです。これらのレコードには、OracleのSDO_PACKAGEを使用するジオメトリ列があります。私はこれらのレコードの間に交差点を見つけなければなりません。 私は十分なpl/sqlクエリを書くが、わずか2千のレコードでは20分かかる。私は実行を完了しようとしますが、330分後にはまだ進行中です。だから私はより速い実行のためにこれらのクエリを改善することができます。ORACLE - このクエリを改善するにはどうすればよいですか?

Sub-Question:挿入部分では、バッファを使用し、最後に一括挿入またはその他の方法で挿入する必要がありますか?

注:私はoracle 11gおよびpl/sql開発者を使用しています。 FirstTableには20000個のレコードがあります。 (ジオメトリ) SecondTable初期値が空です。

declare 
control1 number(1); 
control2 number(1); 
resultForStart varchar2(5); 
resultForEnd varchar2(5); 
BEGIN 
FOR aRow IN (SELECT MI_PRINX, SDO_LRS.geom_segment_start_pt(geoloc) as startpoint, SDO_LRS.geom_segment_end_pt(geoloc) as endpoint FROM FirstTable) 
LOOP 
    control1 :=0; 
    control2 :=0; 
    FOR bRow IN (SELECT * FROM SecondTable) 
    LOOP 
    select SDO_GEOM.RELATE(aRow.Startpoint,'anyinteract', SDO_LRS.geom_segment_start_pt(bRow.Geoloc),0.02) into resultForStart from dual; 
    select SDO_GEOM.RELATE(aRow.Endpoint,'anyinteract', SDO_LRS.geom_segment_end_pt(bRow.Geoloc),0.02) into resultForEnd from dual; 
    if (resultForStart='TRUE' AND control1=0) 
    THEN 
     UPDATE SecondTable SET COUNTER=(bRow.Counter+1) 
      WHERE MI_PRINX=bRow.Mi_Prinx AND STARTEND=bRow.Startend; 
    control1 :=1;   
    END IF; 
    if (resultForEnd='TRUE' AND control2=0) 
    THEN 
     UPDATE SecondTable SET COUNTER=(bRow.Counter+1) 
      WHERE MI_PRINX=bRow.Mi_Prinx AND STARTEND=bRow.Startend; 
    control2 :=1; 
    END IF;   
    EXIT WHEN (control1 > 0 AND control2>0); 
    END LOOP;  
    if (control1 = 0) 
    THEN  
    Insert INTO SecondTable (MI_PRINX,STARTEND,GEOLOC) values (aRow.Mi_Prinx,'s',aRow.Startpoint);--default Counter 1 
    END IF; 
    if (control2 = 0) 
    THEN 
    Insert INTO SecondTable (MI_PRINX,STARTEND,GEOLOC) values (aRow.Mi_Prinx,'e',aRow.Endpoint);--default Counter 1 
    END IF; 
    control1 :=0; 
    control2 :=0; 
END LOOP; 
END; 
+0

SecondTableにはどのようなインデックスがありますか? SecondTableが部分的にいっぱいになると、オプティマイザ統計を収集するようにOracleに指示することもできます。その後、PL/SQLプロシージャを再実行すると、統計によってより高速に実行される可能性があります。 –

+1

挿入物を心配する必要はありませんが、問題はありません。これは、テーブルが大きくなるにつれてループの各サイクル中にSecondTableを再クエリし更新する動作です。または単にアルゴリズムの複雑さです。 –

+0

@ PeterM。 SecondTableの主キーは、Mi_Prinx(数字(10))とStartEnd(varchar2(1))です:複合主キー。そしてMi_PrinxはFirstTableから来ています。既に定義されています。 –

答えて

2

ヒントは次のとおりです。テーブルの行を読み込んで更新しているようです。あなたがこれをしなければならない場合

FOR bRow IN (SELECT * FROM SecondTable) 
    LOOP 
    ... 
    if (resultForStart='TRUE' AND control1=0) 
    THEN 
     UPDATE SecondTable SET COUNTER=(bRow.Counter+1) 
      WHERE MI_PRINX=bRow.Mi_Prinx AND STARTEND=bRow.Startend; 

、代わりにROWIDを使用します。これは、あなたが更新したい行を配置する最速の手段を与える

FOR bRow IN (SELECT * FROM SecondTable) 
    LOOP 
    ... 
    if (resultForStart='TRUE' AND control1=0) 
    THEN 
     UPDATE SecondTable SET COUNTER=(bRow.Counter+1) 
      WHERE ROWID=bRow.rowid; 

+0

私はそれを試みますが、そのテーブルにはROWIDはありません。私のテーブルデザインを変更するか、oracleのrowidを意味するのでしょうか? –

+0

OracleのROWID。 –

+0

私はそれを試みますが、bRow.rowidは動作しません。それはbRow.rowidを宣言しなければならないと言います。 –

関連する問題