使用/ JOIN查询更快地删除

时间:2012-05-30 10:46:45

标签: sql join oracle10g sql-delete

我在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")
)

目前需要大约10秒才能删除50K记录(表中约有100K记录)

我知道它会重复选择查询的100倍,这会大大减慢它的速度 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 个答案:

答案 0 :(得分: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上定义了触发器,您可以尝试禁用它们。他们可以长时间咀嚼更大的删除,我直接了解它。

答案 1 :(得分: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查询应该比这个更快......这会使添加索引答案成为您的最佳选择。但是,可以肯定的是,首先尝试这种新方法。

答案 2 :(得分: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"
            )

答案 3 :(得分: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)  )