web-dev-qa-db-ja.com

dblinkされたOracleテーブルのカーソルからのこのリファクタリングはOKですか?

データは、テーブルのローカルバージョンからコントラクトリンクサーバーのデータと比較されています。そもそもこのコードの目的が何であるかはわかりませんが、少し単純化する方法を模索しています。

CURSOR c3 IS
    SELECT bs.billing_service_id, bs.oser_id
    FROM   (SELECT oser_id
            FROM   other_services
            MINUS
            SELECT oser_id
            FROM   other_services@contracts) a,
           billing_service bs
    WHERE  bs.oser_id = a.oser_id
           AND bs.sent = 0
           AND bs.billing_service_id NOT IN (
               SELECT bd.billing_service_id
               FROM   billing_details bd);

-- snip

FOR c_rec3 IN c3 LOOP
    DELETE FROM billing_service
          WHERE billing_service_id = c_rec3.billing_service_id;
END LOOP;

これは単純に次のように(暗黙の結合やその他のゴミのような他の問題にだまされることなく)素朴にリファクタリングできるように思えます。

    DELETE FROM billing_service
          WHERE billing_service_id IN
(
    SELECT bs.billing_service_id
    FROM   (SELECT oser_id
            FROM   other_services
            MINUS
            SELECT oser_id
            FROM   other_services@contracts) a,
           billing_service bs
    WHERE  bs.oser_id = a.oser_id
           AND bs.sent = 0
           AND bs.billing_service_id NOT IN (
               SELECT bd.billing_service_id
               FROM   billing_details bd)
);

これらのテーブルのデータ量はそれほど多くないと思います。各側に約26000行あり、2つのサブセットの違いのセットがそれほど大きいとは思いません。

しかし、通常のセット指向の方法よりもカーソルを優先するDBリンクに問題があるのではないかと思いました。この操作は、Oracleジョブから毎日実行されるストアドプロシージャの一部です。

1
Cade Roux

Oracleは両方のサイトについて利用可能なすべての情報を持っていないため、データベースリンク間の結合は、最適ではない実行プランにつながる可能性があります。ただし、dbリンクを介したクエリは、ローカルテーブルに結合されている場合は問題なく実行できます(実際に実行されます)。

ローカルテーブルとリモートテーブルを使用して新しいクエリを作成する場合は、すべてを結合し始め(セットベース)、パフォーマンスが許容できない場合や他の調整が機能しない場合にのみ、個別のクエリに分割します。

クエリがリモートサイトへの結合のない単純なマイナスであることを考えると、リファクタリングされたセットベースのアプローチの方が速いと思います。ただし、必ずテストしてください。

3
Chris Saxon