3

我在 Oracle 10g 中有这个查询:

 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 记录大约需要 10 秒(表中大约有 100K 记录)

我知道它会重复 100K 次选择查询,这会减慢它的速度。
TABLE1 也有两个字段的 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 表中添加一个索引

第二个可能的答案:尝试标准 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

试试这个:

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 回答
1

我现在无法测试所以不确定,因为我现在无法访问 Oracle DB,但在某些情况下 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 回答