通过 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 类,用于读取用户表中的所有记录,对其进行哈希处理并更新回用户表。
我正在为 SELECT 和 UPDATE 查询使用准备好的语句 我已将准备好的语句提取大小设置为 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 中找到现有列
用jmeter做oracle数据库测试时,JDBC配置正确,输入语句,执行报错。
PySpark:当通过 JDBC 在 Oracle 中创建表时,为啥我会得到“没有为类 oracle.jdbc.driver.T4CRowidAccessor 实现 getLong”?