データは、テーブルのローカルバージョンからコントラクトリンクサーバーのデータと比較されています。そもそもこのコードの目的が何であるかはわかりませんが、少し単純化する方法を模索しています。
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ジョブから毎日実行されるストアドプロシージャの一部です。
Oracleは両方のサイトについて利用可能なすべての情報を持っていないため、データベースリンク間の結合は、最適ではない実行プランにつながる可能性があります。ただし、dbリンクを介したクエリは、ローカルテーブルに結合されている場合は問題なく実行できます(実際に実行されます)。
ローカルテーブルとリモートテーブルを使用して新しいクエリを作成する場合は、すべてを結合し始め(セットベース)、パフォーマンスが許容できない場合や他の調整が機能しない場合にのみ、個別のクエリに分割します。
クエリがリモートサイトへの結合のない単純なマイナスであることを考えると、リファクタリングされたセットベースのアプローチの方が速いと思います。ただし、必ずテストしてください。