【发布时间】:2014-03-05 11:41:37
【问题描述】:
我只写了几天的 DB2 过程,但试图对给定的表执行“批量删除”。我的预期逻辑是:
- 打开光标
- 穿过它直到 EOF
- 在每次迭代中发出 DELETE
为了简化这个问题,假设我只想在 WHILE 循环完成后(即,一旦光标到达 EOF)发出一个 COMMIT(所有 DELETE)。所以给出下面的代码示例:
CREATE TABLE tableA (colA INTEGER, ...)
CREATE PROCEDURE "SCHEMA"."PURGE_PROC"
(IN batchSize INTEGER)
LANGUAGE SQL
SPECIFIC SQL140207163731500
BEGIN
DECLARE tempID INTEGER;
DECLARE eof_bool INTEGER DEFAULT 0;
DECLARE sqlString VARCHAR(1000);
DECLARE sqlStmt STATEMENT;
DECLARE myCurs CURSOR WITH HOLD FOR sqlStmt;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET eof_bool = 1;
SET sqlString = 'select colA from TableA';
PREPARE sqlStmt FROM sqlString;
OPEN myCurs;
FETCH myCurs INTO tempID;
WHILE (eof_bool = 0) DO
DELETE FROM TableA where colA = tempID;
FETCH myCurs INTO tempID;
END WHILE;
COMMIT;
CLOSE myCurs;
END
注意:在我的真实场景中:
- 我不会从表中删除所有记录,只是根据一些附加条件删除某些记录;和
- 我计划在 WHILE 循环的每 N# 次迭代(比如 500 或 1000)中执行一次 COMMIT,而不是像上面那样一团糟;和
- 我计划删除多个表,而不仅仅是这个;
但再次,为了简化,我测试了上面的代码,我看到的是 DELETE 似乎被一一提交。我基于以下测试:
- 我用(比如 50k)条记录预加载了表格;
- 然后运行 purge storedProc,运行大约需要 60 秒;
- 在此期间,从另一个 sql 客户端,我不断地“SELECT COUNT(*) FROM tableA”并看到计数逐渐减少。
如果一次提交所有 DELETE,我希望看到记录计数 (*) 仅在 ~60 秒结束时从 0 下降。这就是我在为 Oracle 或 SQLServer 编写的类似 SP 中看到的。
这是 Win2003 上的 DB2 v9.5。
任何想法我错过了什么?
【问题讨论】:
-
你的代码一次提交,而不是一个一个提交。你怎么知道代码是一个一个提交? select WITH UR 会告诉你修改的行,但没有提交。
-
我认为您的问题必须更加准时,因为这似乎是一个意见问题,这里不适合提出这样的问题。你必须说出你的问题,展示你做了什么,并清楚地解释你想要得到什么。
-
正如我在下面告诉 Mustaccio 的那样,我猜你们是对的,它正在执行一次提交。一些背景知识...我在 Oracle、SQLServer 和 DB2 中具有相同的数据库结构。我有一个基于 jdbc 的清除应用程序,我可以针对所有 3 个运行它。我现在正在为 3 个 dbs 中的每一个编写一个 storedProcedure 替代方案。 Oracle 和 SQLServer SP 的性能比 JDBC 提高了 10 倍。 DB2 SP 只显示了 2 倍的改进。这种令人惊讶的缓慢,加上看到(我现在意识到是未提交的读取)记录数减少了 1 比 1,这让我认为正在发生额外的提交。
-
嗯...如果可能的话,我仍然建议以基于集合的方式删除(即,不在光标中),因为这应该有助于进一步加快速度。显然,您仍然需要发出多个
DELETEs,但有一些方法可以解决这个问题 - 例如将 id 插入临时表或类似的。仅 50k 条记录的 60 秒非常慢 - 您正在直接读取表(或可能是索引),因此您的大部分时间都花在循环逻辑和逐行删除。 -
我同意@Clockwork-Muse 的观点,在任何 RDBMS 上都会首选一套基础解决方案。 50K 对于单次提交来说应该不是问题。 100K 甚至。 1M 可能是个问题。
标签: sql loops cursor db2 commit