0

delete我在 oracle 中有以下查询。一次将从数据库中删除大约 1000 条记录。

我在查询中使用了“in”。有没有更好的方法来编写这个查询?

DELETE FROM BI_EMPLOYEE_ACTIVITY      
WHERE EMPLOYEE_ID in (    
    SELECT    
      EMP_ID   
    FROM   
      BI_EMPLOYEE   
    WHERE   
      PRODUCT_ID = IN_PRODUCT_ID  
  );
4

6 回答 6

0

将索引放在 EMP_ID 上可能会有所帮助,我不相信是否可以进行任何其他优化,查询非常简单直接

于 2012-09-05T05:30:33.903 回答
0

在 PRODUCT_ID 列上创建索引。这将加快搜索速度。如果列是 varchar 类型,如果要将值转换为大写或小写,请使用函数索引

于 2012-09-05T05:36:11.350 回答
0

也许您可以尝试EXIST而不是 IN:

DELETE FROM BI_EMPLOYEE_ACTIVITY      
WHERE EXISTS (    
    SELECT    
      EMP_ID   
    FROM   
      BI_EMPLOYEE   
    WHERE   
      PRODUCT_ID = IN_PRODUCT_ID 
    AND
      EMP_ID =  EMPLOYEE_ID
  );
于 2012-09-05T05:37:20.283 回答
0

BI_EMPLOYEE按此顺序在表上为PRODUCT_ID, EMP_ID列创建索引(首先是 product_id)。

BI_EMPLOYEE_ACTIVITY并在表上为列创建索引EMPLOYEE_ID

于 2012-09-05T08:02:21.117 回答
0

由于我们缺少对数据分布的描述,因此实际上不可能回答这个问题:每个表中有多少行?表之间有什么关系?删除影响了多少行?

我将假设两个表都很大(因为这是一个优化问题)并且BI_EMPLOYEE具有BI_EMPLOYEE_ACTIVITY父子 1..N 关系。

如果受删除影响的行数很少,这意味着没有多少员工具有相同的PRODUCT_ID内容,并且每个员工的活动很少。BI_EMPLOYEE (product_id)在这种情况下,同时索引和是有意义的BI_EMPLOYEE_ACTIVITY (employee_id)

但这可能不是这种情况,删除可能会影响很多行。在这种情况下,索引可能是一个障碍。如果删除影响很多行,最快的访问路径可能是FULL TABLE SCAN + HASH JOIN.

我们在这里需要一些指标:删除了多少行?多久时间?这是因为大型 DML 总是需要时间,特别是DELETE因为它们产生的撤消量最大。

正如asktom的“从大表中删除许多行”DELETE中所解释的,还有一个 large 的替代方法:

  1. 重新创建没有删除行的表
  2. 对数据进行分区,进行并行删除
  3. 对数据进行分区,以便通过删除分区来完成删除
于 2012-09-05T08:29:18.747 回答
0

我只是补充一点,除了为查询创建索引之外,当表变得非常大时,您需要查看锁定问题,尝试以独占模式锁定表(如果可能),因为这只需要从数据库中锁定,如果不可能尝试对每 2500 条记录提交删除操作,因此如果您遇到行锁定问题,您最终不会让数据库中的锁处于饥饿状态。

于 2012-09-10T21:26:42.507 回答