Java JDBC Delete运行缓慢
我在sql server上的JDBC删除语句中遇到性能问题。 表配置包含约700万行,表详细信息: 列:Java JDBC Delete运行缓慢,java,sql-server,jdbc,Java,Sql Server,Jdbc,我在sql server上的JDBC删除语句中遇到性能问题。 表配置包含约700万行,表详细信息: 列: 终端标识(varchar(50)) 属性(varchar(50)) 价值(nvarchar(1000)) 索引: 终端ID和属性上的聚集唯一索引 代码如下所示,其中属性长度为1500,此程序需要大约1小时才能完成,删除速度非常慢: PreparedStatement statement = null; String sql = "DELETE FROM Config WH
PreparedStatement statement = null;
String sql = "DELETE FROM Config WHERE TERMINAL_ID = ? AND ATTRIBUTE = ?");
for (String attribute : attributes) {
if (statement == null) {
statement = connection.prepareStatement(sqlDelete);
}
statement.setString(1, terminalId);
statement.setString(2, attribute);
statement.executeUpdate();
}
当我在ManagementStudio中运行此查询1500次时,删除只需几秒钟。执行计划如下所示:
当行数较少时,问题就会出现
当我使用createStatement而不是prepareStatement时,问题就出现了。
有什么想法吗?尝试使用
preparedStatement.addBatch()
这可能会提高性能
PreparedStatement statement = null;
String sql = "DELETE FROM Config WHERE TERMINAL_ID = ? AND ATTRIBUTE = ?");
for (String attribute : attributes) {
if (statement == null) {
statement = connection.prepareStatement(sqlDelete);
}
statement.setString(1, terminalId);
statement.setString(2, attribute);
statement.addBatch();
}
statement.executeBatch();
//commit
尝试为此连接禁用自动提交,然后在完成所有delete语句后手动提交:
PreparedStatement statement = null;
String sql = "DELETE FROM Config WHERE TERMINAL_ID = ? AND ATTRIBUTE = ?");
try {
connection.setAutoCommit(false);
for (String attribute : attributes) {
if (statement == null) {
statement = connection.prepareStatement(sqlDelete);
}
statement.setString(1, terminalId);
statement.setString(2, attribute);
statement.executeUpdate();
}
connection.commit();
} finally {
connection.setAutoCommit(true);
}
为了简洁起见,我省略了异常处理。有关更详细的示例,请参见。将prepareStatement移到循环之外
String sql = "DELETE FROM Config WHERE TERMINAL_ID = ? AND ATTRIBUTE = ?");
PreparedStatement statement = connection.prepareStatement(sqlDelete);
for (String attribute : attributes) {
statement.setString(1, terminalId);
statement.setString(2, attribute);
statement.executeUpdate();
}
我发现了问题并解决了它。问题出在方法preparedStatement.setString()中,该方法生成的查询不同,执行计划也不同 我打开了运行查询的SQL Server活动监视器 从配置中删除,其中终端ID=@P0,属性=@P1
因此,我右键单击查询并打开执行计划,如下所示:
正如我猜想的那样,SQLServer正在为每一行调用CONVERT_隐式函数,并在聚集索引中进行扫描。这个软件是第三方的,所以我不得不将专栏改为nvarchar,问题已经解决。我最近遇到了类似的问题,通过JDBC删除性能非常慢 操作非常简单:从t中删除,其中id= id字段是主键 但是,我在perfmon中注意到删除操作触发了完全扫描 据我所知,根本的问题是该列是varchar而不是nvarchar,JDBC驱动程序正在重写delete,以便在查询期间对id进行隐式转换,而不是转换文本值 此转换阻止查询使用索引 当我将专栏切换到使用nvarchar时,问题就消失了
你有关于你的哥伦布的索引吗?你是在一次交易中这样做的吗?@PouriyaZarbafian我在我的文章中提到了集群索引post@Kayaman据我所知,它在单曲中起作用transaction@DavidLekishvili你知道吗?在连接中是否设置了自动提交?每个循环迭代有一次网络往返。我确信花费的时间是网络流量。批处理确实会有所帮助。配置文件以了解时间花在哪里。不要猜,我试图运行这段代码,并在循环和语句之前添加了connection.setAutoCommit(false)。executeBatch();commit();后循环。但它仍然有效,因为prepare语句只发生过一次,因为我已经检查了null。@DavidLekishvili抱歉,今天这么早就开始。。。你需要在代码中开始计时,看看它在哪里卡住了。一些基本的打印和当前时间。你需要消除每一步。连接需要10秒,删除需要1秒吗?你写的东西没有明显的错误,所以你需要找出问题所在。如果它在数据库中,可能会清除缓存(错误的查询计划会消除索引的使用?@DavidLekishvili最后一件显而易见的事情是将delete放入存储过程中,并使用正确的值调用存储过程。这将消除一个错误的查询计划,并且您应该看到SSMS客户端和JDBC客户端的性能是一致的。preparedStatement存在问题,因为对于createStatement,它可以在几秒钟内正常工作。