Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JDBC Delete运行缓慢_Java_Sql Server_Jdbc - Fatal编程技术网

Java JDBC Delete运行缓慢

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

我在sql server上的JDBC删除语句中遇到性能问题。 表配置包含约700万行,表详细信息:

列:

  • 终端标识(varchar(50))
  • 属性(varchar(50))
  • 价值(nvarchar(1000))
  • 索引: 终端ID和属性上的聚集唯一索引

    代码如下所示,其中属性长度为1500,此程序需要大约1小时才能完成,删除速度非常慢:

         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,它可以在几秒钟内正常工作。