3

Oracle10gでこのクエリがあります。

 DELETE FROM "BMAN_TP1"."CELLS_ITEM" TABLE1
 WHERE EXISTS (
     SELECT "CELLS_ITEM".*
     FROM "BMAN_TP1"."CELLS_ITEM"
     INNER JOIN "BMAN_TP1"."CELLS" ON ("CELLS_ITEM"."SET_ID"="CELLS"."SET_ID") AND ("CELLS_ITEM"."META_CELL_ID"="CELLS"."META_CELL_ID")
     INNER JOIN "BMAN_TP1"."META_CELLS" ON ("CELLS"."META_CELL_ID"="META_CELLS"."META_CELL_ID")
     WHERE ("META_CELLS"."UDA_ID" = variable)
     AND (TABLE1."SET_ID" = "CELLS_ITEM"."SET_ID")
     AND (TABLE1."META_CELL_ID" = "CELLS_ITEM"."META_CELL_ID")
)

現在、50Kレコード(およびテーブル内の約100Kレコード)を削除するには約10秒かかります

選択クエリが100K回繰り返されるため、処理速度が大幅に低下することはわかっています。
また、TABLE1には2つのフィールドPKがあり、これにより作業がより複雑になります。

それを速くするためのアイデアはありますか?

編集:

これを試しましたが、ほぼ同じです。

DELETE FROM "BMAN_TP1"."CELLS_ITEM" TABLE1
WHERE EXISTS (
    SELECT "META_CELL_ID"
    FROM "BMAN_TP1"."META_CELLS"
    WHERE ("META_CELLS"."UDA_ID"=55823)
    AND (TABLE1."META_CELL_ID" = "META_CELLS"."META_CELL_ID")
)
4

4 に答える 4

4

スキーマがわからないとわかりにくいですが、サブクエリで削除したいテーブルを使用しても無駄に思えます。代わりに次のように書きます。

DELETE FROM BMAN_TP1.CELLS_ITEM TABLE1
WHERE EXISTS (
    SELECT CELLS.META_CELL_ID
    FROM BMAN_TP1.CELLS 
    INNER JOIN BMAN_TP1.META_CELLS ON (CELLS.META_CELL_ID=META_CELLS.META_CELL_ID)
    WHERE (META_CELLS.UDA_ID = variable)
        AND (TABLE1.SET_ID = CELLS_ITEM.SET_ID)
        AND (TABLE1.META_CELL_ID = CELLS_ITEM.META_CELL_ID)
)

編集DELETE:ステートメントを変更したため、上記は現在日付が付けられています。無視してください。

しかし、別のアイデア: CELLS_ITEM にトリガーが定義されている場合は、それらを無効にしてみてください。彼らはかなり長い間、より大きな削除を噛むことができます.私はそれを直接知っています.

于 2012-05-30T11:07:41.510 に答える
2

最初の可能な答え: SET_ID、META_CELL_ID の CELLS_ITEM テーブルにインデックスを追加するだけです

2 番目に考えられる答え: 標準の SQL 構文を試してください。

DELETE "BMAN_TP1"."CELLS_ITEM"
  FROM BMAN_TP1"."CELLS_ITEM"  
 INNER JOIN "BMAN_TP1"."CELLS" ON ("CELLS_ITEM"."SET_ID"="CELLS"."SET_ID") AND ("CELLS_ITEM"."META_CELL_ID"="CELLS"."META_CELL_ID")  
 INNER JOIN "BMAN_TP1"."META_CELLS" ON ("CELLS"."META_CELL_ID"="META_CELLS"."META_CELL_ID")  
 WHERE ("META_CELLS"."UDA_ID" = variable)  

-- 編集

Oracle が標準 SQL の方法を受け入れないことが本当なら (奇妙に聞こえます)、IN を使用してみてください。

DELETE "BMAN_TP1"."CELLS_ITEM"
 WHERE (SET_ID, META_CELL_ID) IN (SELECT SET_ID, META_CELL_ID
                                    FROM BMAN_TP1"."CELLS_ITEM"  
                                         INNER JOIN "BMAN_TP1"."CELLS" ON ("CELLS_ITEM"."SET_ID"="CELLS"."SET_ID") AND ("CELLS_ITEM"."META_CELL_ID"="CELLS"."META_CELL_ID")  
                                         INNER JOIN "BMAN_TP1"."META_CELLS" ON ("CELLS"."META_CELL_ID"="META_CELLS"."META_CELL_ID")  
                                   WHERE ("META_CELLS"."UDA_ID" = variable)  )

しかし、EXISTSクエリはこれよりも高速である必要があると思います...これにより、インデックスの回答を追加することが最善の選択肢になります。ただし、念のため、この新しいアプローチを最初に試してください。

于 2012-05-30T11:02:40.610 に答える
1

現在OracleDBにアクセスできないため、現時点ではテストできませんが、rowidの方が高速な場合があります。

   DELETE "BMAN_TP1"."CELLS_ITEM"
 WHERE rowid IN (SELECT rowid
                                    FROM BMAN_TP1"."CELLS_ITEM"  
                                         INNER JOIN "BMAN_TP1"."CELLS" ON ("CELLS_ITEM"."SET_ID"="CELLS"."SET_ID") AND ("CELLS_ITEM"."META_CELL_ID"="CELLS"."META_CELL_ID")  
                                         INNER JOIN "BMAN_TP1"."META_CELLS" ON ("CELLS"."META_CELL_ID"="META_CELLS"."META_CELL_ID")  
                                   WHERE ("META_CELLS"."UDA_ID" = variable)  )
于 2013-03-06T11:11:53.110 に答える
1

これを試して:

DELETE FROM (SELECT TABLE1.* FROM "BMAN_TP1"."CELLS_ITEM" TABLE1
                INNER JOIN (
                    SELECT "META_SET_ID", "META_CELL_ID"
                    FROM "BMAN_TP1"."META_CELLS"
                    WHERE "UDA_ID"=55823
                ) j ON TABLE1."SET_ID" = j."META_SET_ID" AND TABLE1."META_CELL_ID" = j."META_CELL_ID"
            )
于 2012-05-30T13:51:33.113 に答える