Sau*_*wal 4 database db2 performance db2-luw
我正在使用DB2 9.7 FP5 for LUW.我有一个250万行的表,我想删除大约100万行,这个删除操作分布在表中.我正在使用5个删除语句删除数据.
delete from tablename where tableky between range1 and range2
delete from tablename where tableky between range3 and range4
delete from tablename where tableky between range5 and range5
delete from tablename where tableky between range7 and range8
delete from tablename where tableky between range9 and range10
Run Code Online (Sandbox Code Playgroud)
在执行此操作时,前3个删除工作正常但第4个失败并且DB2挂起,什么都不做.以下是我遵循的流程,请帮助我:
1. Set following profile registry parameters: DB2_SKIPINSERTED,DB2_USE_ALTERNATE_PAGE_CLEANING,DB2_EVALUNCOMMITTED,DB2_SKIPDELETED,DB2_PARALLEL_IO
2.Alter bufferpools for automatic storage.
3. Turn off logging for tables (alter table tabname activate not logged initially) and delete records
4. Execute the script with +c to make sure logging is off
Run Code Online (Sandbox Code Playgroud)
删除如此大量数据的最佳做法是什么?为什么在从同一个表中删除数据并且具有相同性质时失败?
这是一项非常棘手的任务.事务的大小(例如,安全回滚)受事务日志大小的限制.事务日志不仅由您的sql命令填充,而且还由在同一时刻使用db的其他用户的命令填充.
我建议使用以下方法中的一种/或组合
经常提交 - 在你的情况下,我会在每个删除命令后放一个提交
我记得默认db2事务日志不是很大.应分别为每个数据库计算/调整事务日志的大小.参考这里和更多的细节在这里
编写并调用存储过程,它会在块中删除,例如:
Run Code Online (Sandbox Code Playgroud)-- USAGE - create: db2 -td@ -vf del_blocks.sql -- USAGE - call: db2 "call DEL_BLOCKS(4, ?)" drop PROCEDURE DEL_BLOCKS@ CREATE PROCEDURE DEL_BLOCKS(IN PK_FROM INTEGER, IN PK_TO INTEGER) LANGUAGE SQL BEGIN declare v_CNT_BLOCK bigint; set v_CNT_BLOCK = 0; FOR r_cur as c_cur cursor with hold for select tableky from tablename where tableky between pk_from and pk_to for read only DO delete from tablename where tableky=r_cur.tableky; set v_CNT_BLOCK=v_CNT_BLOCK+1; if v_CNT_BLOCK >= 5000 then set v_CNT_BLOCK = 0; commit; end if; END FOR; commit; END@
在某些情况下,当我需要清除非常大的表或只留下少量记录(并且没有FK约束)时,我使用了export + import(replace).替换导入选项非常具有破坏性 - 它在导入新记录之前清除整个表(db2 import命令的引用),因此请确保您正在做什么并在之前进行备份.对于这样的敏感操作,我创建3个脚本并分别运行:备份,导出,导入.这是导出脚本:
echo '===================== export started ';
values current time;
export to tablename.del of del
select * from tablename where (tableky between 1 and 1000
or tableky between 2000 and 3000
or tableky between 5000 and 7000
) ;
echo '===================== export finished ';
values current time;
Run Code Online (Sandbox Code Playgroud)
这是导入脚本:
echo '===================== import started ';
values current time;
import from tablename.del of del allow write access commitcount 2000
-- !!!! this is IMPORTANT and VERY VERY destructive option
replace
into tablename ;
echo '===================== import finished ';
Run Code Online (Sandbox Code Playgroud)
版本9.7中的Db2引入了TRUNCATE语句:
删除表中的所有行.
基本上:
TRUNCATE TABLE <tablename> IMMEDIATE
Run Code Online (Sandbox Code Playgroud)
我在db2中没有使用TRUNCATE的经验,但在其他一些引擎中,命令非常快,并且不使用事务日志(至少不是通常的方式).请在此处或官方文档中查看所有详细信息.作为解决方案4,这种方法也非常具有破坏性 - 它会清除整个表,因此在发出命令之前要非常小心.确保先前使用表/数据库备份执行的状态.
当db上没有其他用户时,或通过锁定表来确保这一点.
在事务db(如db2)中,回滚可以将db状态恢复到事务启动时的状态.在方法1,3和4中,这是无法实现的,因此如果您需要"恢复到原始状态"的功能,唯一可以确保这一点的方法是nr.2 - 增加事务日志.