如何频繁提交以使我的sql删除查询赢得';t超时

如何频繁提交以使我的sql删除查询赢得';t超时,sql,db2,spring-batch,Sql,Db2,Spring Batch,在我的Spring批处理项目中,我有几个更新/删除查询作为单个任务的一部分,它们正在超时,因为它们正在删除大量记录。 因为这些只是更新和删除查询,所以我将它们实现为不面向块的Tasklet步骤 我如何能够频繁提交,以避免超时 public class DeleteTask implements Tasklet { private static final String DELETE_QUERY = "DELETE FROM MYTABLE WHERE COLUMN = 'TE

在我的Spring批处理项目中,我有几个更新/删除查询作为单个任务的一部分,它们正在超时,因为它们正在删除大量记录。 因为这些只是更新和删除查询,所以我将它们实现为不面向块的Tasklet步骤

我如何能够频繁提交,以避免超时

public class DeleteTask implements Tasklet {

    private static final String DELETE_QUERY = "DELETE FROM MYTABLE WHERE COLUMN = 'TEST'";
    private JdbcTemplate jdbcTemplate;


    public DeleteTask(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }


    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
        log.info("Purging IMCO records from MYTABLE table...");
        try {
            jdbcTemplate.update(DELETE_QUERY);
        } catch (Exception e) {
            log.info("Failed to purge  records from MYTABLE table due to:");
            log.info(e.getMessage());
        }
        log.info("Records purged");
        return RepeatStatus.FINISHED;
    }
}
编辑: 例外情况如下:

 StatementCallback; SQL [DELETE FROM MYTABLE WHERE LOB_CD = 'TEST'[jcc][t4][2055][11259][4.14.113] The database manager is not able to accept new requests, has terminated all requests in progress, 
ERRORCODE=-4499, SQLSTATE=58009; nested exception is com.ibm.db2.jcc.am.DisconnectNonTransientException: [jcc][t4][2055][11259][4.14.113] The database manager is not able to accept new requests, has terminated all requests in progress, 


我可以想出两种策略:

增加查询超时时间

您可以使用
java.sql.Statement.setQueryTimeout()
增加特定查询的超时时间,但这只能在一定程度上帮助您

批量删除

另一个选项是迭代运行
DELETE
语句,限制已删除行的数量,直到不再删除更多行(因此所有行都消失)。您可以将
仅获取下n行
添加到
删除
以实现此目的

例如:

create table t (a int);
insert into t (a) values (1001);
insert into t (a) values (1002);
insert into t (a) values (1003);
insert into t (a) values (1004);
delete from t fetch next 2 rows only;
select * from t;
结果:

A
----
1003
1004
每次运行查询时,它都会告诉您已删除行的行数。继续运行它,直到返回的计数为零

对于您的特殊情况,您需要调整批次大小。例如,对于每次10k行,您可以使用
仅获取下10000行
。数字越大,速度越快,但也有超时的风险


参见运行示例。

我可以想到两种策略:

增加查询超时时间

您可以使用
java.sql.Statement.setQueryTimeout()
增加特定查询的超时时间,但这只能在一定程度上帮助您

批量删除

另一个选项是迭代运行
DELETE
语句,限制已删除行的数量,直到不再删除更多行(因此所有行都消失)。您可以将
仅获取下n行
添加到
删除
以实现此目的

例如:

create table t (a int);
insert into t (a) values (1001);
insert into t (a) values (1002);
insert into t (a) values (1003);
insert into t (a) values (1004);
delete from t fetch next 2 rows only;
select * from t;
结果:

A
----
1003
1004
每次运行查询时,它都会告诉您已删除行的行数。继续运行它,直到返回的计数为零

对于您的特殊情况,您需要调整批次大小。例如,对于每次10k行,您可以使用
仅获取下10000行
。数字越大,速度越快,但也有超时的风险


请参见运行示例。

一个简单的SQL复合语句可能是最好的方法

BEGIN
    DECLARE DONE BOOLEAN DEFAULT FALSE;  
    --
    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' BEGIN SET DONE = TRUE; END;
    --
    WHILE NOT DONE
    DO
        DELETE FROM (SELECT * FROM MY_TABLE WHERE COL1 = 'A' FETCH FIRST 20000 ROWS ONLY)
        COMMIT;
    END WHILE;
END

一个简单的SQL复合语句可能是最好的方法

BEGIN
    DECLARE DONE BOOLEAN DEFAULT FALSE;  
    --
    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' BEGIN SET DONE = TRUE; END;
    --
    WHILE NOT DONE
    DO
        DELETE FROM (SELECT * FROM MY_TABLE WHERE COL1 = 'A' FETCH FIRST 20000 ROWS ONLY)
        COMMIT;
    END WHILE;
END


你有什么例外?您要删除多少行?这个表有多少行?不确定这个表有多少行,但我们说的是数千万行。我正在尝试删除大约700万行。编辑帖子以显示异常您是否增加了连接/事务超时值?这是在哪里添加的?您得到了什么异常?您要删除多少行?这个表有多少行?不确定这个表有多少行,但我们说的是数千万行。我正在尝试删除大约700万行。编辑post以显示异常您是否增加了连接/事务超时值?这是在哪里添加的?除了批量删除(每批提交一次)之外,您还需要仔细验证运行的DELETE语句是否正确索引(因此请仔细检查访问计划),否则,您将执行多个表扫描,这将大大降低查询速度并导致并发问题。此外,如果您知道将通过此操作清除的行的百分比,并且该百分比超过行的60%,则更智能的策略是将40%的行复制到临时表中,截断表(未标记),然后复制回40%。使用频繁提交是有意义的。谢谢你的例子@theimpaler,我想我的最后一个问题是如何合并并重新运行查询?我将使用什么样的循环/条件,以便在确定所有行后退出。除了分批删除(每批提交一次)之外,您还需要仔细验证运行的DELETE语句是否正确索引(因此请仔细检查访问计划),否则,您将执行多个表扫描,这将大大降低查询速度并导致并发问题。此外,如果您知道将通过此操作清除的行的百分比,并且该百分比超过行的60%,则更智能的策略是将40%的行复制到临时表中,截断表(未标记),然后复制回40%。使用频繁提交是有意义的。谢谢你的例子@theimpaler,我想我的最后一个问题是如何合并并重新运行查询?我将使用什么样的循环/条件,以便在所有行都被删除后它将退出looks good@Paul Vernon,在这种情况下,我是否必须将SQLSTATE“02000”更改为我在上述异常中得到的特定代码?不,SQLSTATE是“未找到行”,因此循环将继续,直到删除所有符合条件的行。如果我的答案对您有效,请随意接受它,或者投票给itOk酷毙了谢谢Paul,等我回到我的机器并能够测试
之后发现一个意外的标记“DO”“虽然未完成
看起来不错@Paul Vernon,但在这种情况下,我是否必须将SQLSTATE'02000'更改为我在上述异常中得到的特定代码?不,SQLSTATE是“未找到行”,因此循环将继续,直到删除所有符合条件的行。如果我的答案对您有效,请随意接受它,或者投票给我,谢谢Paul,一旦我回到我的机器,并且能够测试
在“未完成时”之后发现意外的标记“DO”