【问题标题】:Optimize of hibernate delete operation优化休眠删除操作
【发布时间】:2014-08-12 23:10:21
【问题描述】:

下面的代码可以运行,但是当 SQL 删除超过一百万行时会出现性能问题。删除 2M 表需要很长时间,大约需要 1 小时。我们无法控制传递给我们的 sql 条件。有没有更好的方法让它运行得更快?

除此之外,我们没有数据库管理员访问权限,因此存储过程不能成为解决方案。任何帮助是极大的赞赏。谢谢

示例 SQL 查询

DELETE TBL_A WHERE ID IN (SELECT ID FROM TBL_B WHERE 1=1 AND TBL_B.BD < TO_DATE(ADD_MONTHS(SYSDATE, -240)));

删除方法

 public void deleteRows(String table, String condition){

    StringBuilder sql = new StringBuilder();
    sql.append("DELETE TABLE=:TABLE WHERE CONDITION=:CONDITION ");

    try{
    transaction = session.beginTransaction();

    int rows = session.createSQLQuery(sql.toString()).setParamater("TABLE",TABLE).setParameter("CONDITION",CONDITION).executeUpdate();

    transaction.commit();
    }
    catch{
    //logic here
    }
    }

【问题讨论】:

    标签: java hibernate jakarta-ee oracle11g


    【解决方案1】:

    对于这个特定的“问题”没有更快的方法。不幸的是,这不是性能问题,而是应用程序设计问题。

    ...但是...

    你可以:

    1. 使用与原始表相同的单个分区和一组索引创建表的列表分区副本。
    2. insert /*+ append */ into the replica select * from the original 表与NOTCONDITION 一起使用。
    3. 将单副本分区与原始表交换。
    4. Truncate 带有drop storage 选项的单副本分区。

    更具体的答案需要更具体的问题。

    【讨论】:

    • 感谢 nop,所以我们优化应用删除操作性能的唯一方法是更改​​ SQL 条件本身,对吗?
    • 不完全。我的建议是,与其通过 DELETE 删除大量行,不如使用类似“DWH”的方法并将互补行(通过直接加载!)插入到不同的表中,然后交换两个表(通过分区交换)。但是,一般来说,最终的解决方案实际上非常依赖于我们正在谈论的数据量,您有哪些更改表组织的选项等等。 :-(
    • 另外,对于您在问题中发布的特定示例查询...尝试在 TBL_B (BD, ID)TBL_A (ID) 上创建索引,如果您还没有这些索引,并且有统计信息在 TBL_ATBL_B 上重新计算。这可能有助于查询的潜在次优执行计划。唉,在不了解您的应用程序、正在使用的所有执行计划、您的表结构和数据量的情况下,我无法为您的性能问题提出解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 2011-02-16
    • 2012-02-07
    相关资源
    最近更新 更多