作者:桦林ye家伟 | 来源:互联网 | 2023-09-12 13:23
我现在有A、B、C、D、E、F、G,7个表,当删除A表时,A表有触发器同时删除B、C、D、E、F、G的数据,只删除A表的一条记录时,数度很快。但是当A表有700万数据,而我要带where条件删除500
我现在有A、B、C、D、E、F、G,7个表,当删除A表时,A表有触发器同时删除B、C、D、E、F、G的数据,只删除A表的一条记录时,数度很快。但是当A表有700万数据,而我要带where条件删除500万同时删除另外6个表的相关数据,delete A where status = 1语句就会很慢。因为这条语句由于A表上有触发器,它要删除的数据会是7个表的要删除数据的总和,有5000万之多。它要对日志进行大量的写入操作。
如果是用oracle数据库,可以用alter table XXX nologging来使7个表对的任何操作
都不写日志,delete from A where status = 1就会很快。
如果是用sybase数据库,可以在启动时带一个特别参数来使整个数据库对任何操作都
不写日志,达到同样的效果。
但是我在ms-sql server却找不到oracle或是sybase那样的方法。这里有人知道如何做吗?
31 个解决方案
汗,不知道,楼主的题目太上纲上线了,我立马查资料去
use master
exec sp_dboption 'yourdbname','trunc. log on chkpt.','true'
try
use master
exec sp_dboption 'yourdbname',trunc. log on chkpt.','true'
sorry,刚才写错了,具体可以查看master.dbo.spt_values
楼上的好像不行
trunc. log on chkpt. 当为 true 时,如果数据库处于日志截断模式,则检查点将截断日志中非活动的部分。只能为 master 数据库设置此选项。
楼上的方法是让'yourdbname'的日志在检查点截断日志,不是操作时不写日志,是写完日志事务提交后日志自动截断。还是要写日志耗费时间的。
to:KnowLittle(人傻不要紧,只要肯学习。)
我是觉得这个问题棘手,所以出这样的题目是想引起注意。
请大家不要生气我这样提问。
不带日志全部删除某个表的全部数据倒是用过,的确快,但是没有用过加条件的大量删除。
没啥,没啥,只要你不是来摆擂的就行,呵呵
等待高手出现ing,
查资料ingp
to: DJMPH(冷开水)
是的,truncate table XXX是很快的。
langtian
看一下
http://expert.csdn.net/Expert/topic/1140/1140756.xml?temp=.6834833
好象没什么好办法:
试试:
set rowcount 10000
while 1=1
delete ....
看过了,
那个帖子的两种答案我都试过,但是都行不通。
第一种:在循环中设置rowcount有问题,应为我的其它表的数据会是A表的好几倍,这样会出现删除A表中的1000行,其它表也是1000行,其它表没有删除干净。
第二种:我要关联同时删除7个表的数据,用先bcp再truncate的方法要重复操作7个表,比较麻烦,也容易出错。
所以那个帖子的两种方法在我遇到的情况都不行。
说句提外话:
为什么要让用户一下删除这么多数据那?而且是级联删除那么多表的操作
我感觉这种级别的操作应该是数据维护的时候(或者数据仓库导入,更新的时候)才需要用到,可以做成job放到深夜或者专门时间,慢一点是可以理解的阿
而且日志不写对于数据以后的维护和恢复也是不利的
哦,我是在数据维护的时候做这个操作,这个操作让用户干的话,我们的系统就完蛋了。因为我们的系统必须保持24小时绝对可用,晚上的用户也很多,我能在55个小时删除这几千万数据(循环一次删一条),但是有很大风险。所以想删除快一点,
呵呵。
langtian
to:KnowLittle(人傻不要紧,只要肯学习。)
你是对的,实在不行的话就只有关掉系统慢慢删,呵呵。
我认为可以选得到所有要删除的ID,这可从表DELETED表中得到
删除其它表则用WHERE Id in()就可以删除相应的记录啰
楼上的想法不错
但是楼主的trigger不一定是如此简单的逻辑
现在且不谈删除,我们来看看大容量复制对事务日志的操作:
使用完整恢复模式时,所有由 bcp 执行的行插入操作都记录在事务日志中。如果数据量较大,会造成事物日志迅速写满。为了防止事务日志耗尽空间,当符合以下全部条件时,可以执行最小日志记录的大容量复制:
1、恢复模式是简单模式或大容量日志记录模式。
2、没有正在复制目标表。
3、目标表没有任何触发器。
4、目标表具有 0 行或没有索引。
任何不满足上述条件的SQL Server实例的大容量复制都将记入日志。
如果是按照这样的条件话,估计以上的删除操作(带触发器)再SQL中是不可能不写入日志的。
笨辦法,先把不刪的資料拉到另外的表中,
再把原來的表資料全部刪除再倒入或
用另外的表替換原來的表,呵呵~
這個方法笨不笨~
你的问题其实是递归触发的问题,你可以从2方面来试试:
1.解决DISK I/O的问题,比如不要记录日志,设置一次删除的行数...
CABO(白椒腊肉),j9988(j9988)的方法。
2.配置 TRIGGER SQL的参数.
FOR EXAMPLE:
1.--禁用间接递归
USE master0
EXEC sp_configure 'nested triggers', '3'
RECONFIGURE WITH OVERRIDE
--Need restart SQL SERVER SERVICE
2.--禁用直接递归
SET RECURSIVE_TRIGGERS OFF
3.
3.手工写T-SQL,删除A表的记录和相关的B,C....。
4.SET RECURSIVE_TRIGGERS ON
sorry:
USE master0
EXEC sp_configure 'nested triggers', '0'
RECONFIGURE WITH OVERRIDE
--Need restart SQL SERVER SERVICE
不写日志可能做不到。MSSQL没有这个选项。只有某些操作可以不写日志。
以前有个贴子讨论过这个问题。可以用select into将不删除的数据放到新表里去.(这个操作不写日志)然后用tuncate table (也不写日志)\drop table删除整原表)。这样可以日志少点。但是好不好很难说。
按钮jj下午好!
还得让盖茨把这个功能完善一下!!哈哈!!
exec sp_dboption yourDB,'trunc. log on chkpt.',true
就可以在INSERT,UPDATE,DELETE时不写日志了,