通过 JDBC 在 Oracle 中 SELECT 和 UPDATE 100 万行的性能不佳

Posted

技术标签:

【中文标题】通过 JDBC 在 Oracle 中 SELECT 和 UPDATE 100 万行的性能不佳【英文标题】:Poor performance to SELECT and UPDATE one million rows in Oracle via JDBC 【发布时间】:2016-12-26 23:15:17 【问题描述】:

我有一个包含超过 100 万行的用户表(Oracle 11g DB),其中包含我尝试使用 SHA512 算法(散列和盐)散列的所有用户密码。下面开始是我的 Java 类,用于读取用户表中的所有记录,对其进行哈希处理并更新回用户表。

我正在为 SELECTUPDATE 查询使用准备好的语句 我已将准备好的语句提取大小设置为 1000 (setFetchSize(1000)) 我已将自动提交属性设置为 false 使用批处理方式进行批量更新
try 
    ps = con.prepareStatement("update user set password=? where ID=?");
    psSel = con.prepareStatement("select ID, password from user");
    psSel.setFetchSize(1000);
    rs = psSel.executeQuery();
    String hashPassword = null;
    while (rs.next()) 
        long id = rs.getLong(1);
        String pwd = rs.getString(2);
        hashPassword = <<CALL TO PASSWORD HASHING UTIL>>;
        ps.setString(1, hashPassword);
        ps.setLong(2, id);
        ps.addBatch();

      //Every 5000 records update and commit
        if(++count % batchSize == 0) 
            ps.executeBatch();
            con.commit();
        

    
    ps.executeBatch();
    con.commit();
 catch (SQLException e) 
    e.printStackTrace();

更新100,000条记录,上面的方法需要将近8分钟,我觉得相当高。

使用的数据库: Oracle 11g

Java 版本: 1.6

环境:Windows 7

我不确定我是否遗漏了什么。您能否建议或推荐任何处理此类批量负载的最佳方法?

更新

我再次查看了我之前创建的 USER 临时表,可以看到 ID 列中没有添加 主键约束。我继续为 ID 列添加 PK 约束并重新运行我的实用程序。现在处理 100,000 行只需要 36 秒

为了确保我还创建了另一个没有 PK 约束的临时表 USER_TMP2 并运行了我的实用程序,它像往常一样花了 8 分钟 100,000 >

【问题讨论】:

8 分钟 hash 并在 DB 中更新 100 万条记录似乎并不高 你能在数据库端复制你的哈希函数吗?如果是这样,您可以进行一次更新,而无需通过网络将所有数据移入和移出 Java。但目前尚不清楚瓶颈在哪里。 为什么不在DBMS_CRYPTO 中使用HASH_SH512 您是否进行了任何基本调试,例如分析代码?就你所知,数据库的东西用了 0.1 秒,另外 7 分钟 59.9 秒用在了你的哈希函数中。 @Sachin - 您可以编写一个 Java 存储过程,该过程使用 Java 的散列功能但在数据库中运行,这当然假设盐可用于数据库。而网络旅行实际上是瓶颈。 【参考方案1】:

我再次查看了临时表 - 我之前创建的 USER,可以看到 ID 列中没有添加主键约束。我继续为 ID 列添加 PK 约束并重新运行我的实用程序。现在处理 100,000 行只需要 36 秒。

为了确保我还创建了另一个没有 PK 约束的临时表 USER_TMP2 并运行了我的实用程序,它像往常一样花了 8 分钟来获得 100,000

故事的寓意:在调查性能不佳时,第一件事要做的是调查所涉及的表的索引 - 通过简单检查或查看查询的执行计划 - 以确保你没有做很多不必要的表扫描。

【讨论】:

【参考方案2】:

查看用户表,并从该表中获取数据。这将优化您的查询执行时间。它可能对您的情况有所帮助。

【讨论】:

创建视图不会优化查询执行

以上是关于通过 JDBC 在 Oracle 中 SELECT 和 UPDATE 100 万行的性能不佳的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中读取 SQL 文件以通过 databricks 对 JDBC 运行

SQLite 无法通过 JDBC 和 jOOQ 在 SELECT 中找到现有列

如何通过 JDBC 从 Db2 匿名块返回动态结果集?

用jmeter做oracle数据库测试时,JDBC配置正确,输入语句,执行报错。

PySpark:当通过 JDBC 在 Oracle 中创建表时,为啥我会得到“没有为类 oracle.jdbc.driver.T4CRowidAccessor 实现 getLong”?

如何通过 JDBC 将 Java 存储过程加载到 Oracle 10g 中?