大規模がある場合 アプローチに問題がある場合は、clean.id
列のインデックスが欠落している可能性があります。 、MERGE
の場合のアプローチに必要です dual
を使用します 各行のソースとして。
id
を言っている間、これは起こりそうにありません。 主キーです 。
したがって、基本的に あなたは正しい考えをしていて、実行計画 が表示されます。 以下のようなものです:
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | MERGE STATEMENT | | | | 2 (100)| |
| 1 | MERGE | CLEAN | | | | |
| 2 | VIEW | | | | | |
| 3 | NESTED LOOPS OUTER | | 1 | 40 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL | DUAL | 1 | 2 | 2 (0)| 00:00:01 |
| 5 | VIEW | VW_LAT_A18161FF | 1 | 38 | 0 (0)| |
| 6 | TABLE ACCESS BY INDEX ROWID| CLEAN | 1 | 38 | 0 (0)| |
|* 7 | INDEX UNIQUE SCAN | CLEAN_UX1 | 1 | | 0 (0)| |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
7 - access("CLEAN"."ID"=:ID)
したがって、実行計画は問題なく効果的に機能しますが、問題が1つあります。
常にインデックスを使用することを忘れないでください。数行を処理していても問題はありませんが、スケーリングは行われません 。
数百万を処理している場合 レコードの場合、2段階の処理にフォールバックできます。
-
一時テーブルにすべての行を挿入します
-
単一の
MERGE
を実行します 一時テーブルを使用したステートメント
大きな利点 Oracleはhash join
を開くことができるということです millionごとにインデックスアクセスを削除します 行。
ここにclean
のテストの例があります 1Mのid
で開始されたテーブル (図には示されていません)および1M挿入と1M更新の実行:
n = 1000000
data2 = [{"id" : i, "xcount" :1} for i in range(2*n)]
sql3 = """
insert into tmp (id,count)
values (:id,:xcount)"""
sql4 = """MERGE into clean USING tmp on (clean.id = tmp.id)
when not matched then insert (id, count) values (tmp.id, tmp.count)
when matched then update set clean.count= clean.count + tmp.count"""
cursor.executemany(sql3, data2)
cursor.execute(sql4)
テストは約で実行されます。 10秒、これはMERGE
でアプローチする半分未満です dual
を使用する 。
それでも不十分な場合は、並列オプションを使用する必要があります。 。