热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

一个考验国人对ms-sqlserver掌握水平的问题!

我现在有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 个解决方案

#1


汗,不知道,楼主的题目太上纲上线了,我立马查资料去

#2


use  master  
exec  sp_dboption  'yourdbname','trunc.  log  on  chkpt.','true'  

try

#3


use  master  
exec  sp_dboption  'yourdbname',trunc. log on chkpt.','true'  

sorry,刚才写错了,具体可以查看master.dbo.spt_values 

#4


楼上的好像不行
trunc. log on chkpt. 当为 true 时,如果数据库处于日志截断模式,则检查点将截断日志中非活动的部分。只能为 master 数据库设置此选项。

#5


楼上的方法是让'yourdbname'的日志在检查点截断日志,不是操作时不写日志,是写完日志事务提交后日志自动截断。还是要写日志耗费时间的。

#6


刚才查了一下,没错,不行,呵呵
学习中。。。

#7


只能为 master 数据库设置此选项

非也

#8


to:KnowLittle(人傻不要紧,只要肯学习。)
我是觉得这个问题棘手,所以出这样的题目是想引起注意。
请大家不要生气我这样提问。

#9


不带日志全部删除某个表的全部数据倒是用过,的确快,但是没有用过加条件的大量删除。

#10


没啥,没啥,只要你不是来摆擂的就行,呵呵
等待高手出现ing, 
查资料ingp

#11


to: DJMPH(冷开水) 
    是的,truncate table XXX是很快的。
                            langtian

#12


看一下
http://expert.csdn.net/Expert/topic/1140/1140756.xml?temp=.6834833

#13


好象没什么好办法:
试试:
set rowcount 10000
while 1=1
delete ....

#14


看过了,
那个帖子的两种答案我都试过,但是都行不通。
第一种:在循环中设置rowcount有问题,应为我的其它表的数据会是A表的好几倍,这样会出现删除A表中的1000行,其它表也是1000行,其它表没有删除干净。
第二种:我要关联同时删除7个表的数据,用先bcp再truncate的方法要重复操作7个表,比较麻烦,也容易出错。
所以那个帖子的两种方法在我遇到的情况都不行。

#15


说句提外话:

为什么要让用户一下删除这么多数据那?而且是级联删除那么多表的操作
我感觉这种级别的操作应该是数据维护的时候(或者数据仓库导入,更新的时候)才需要用到,可以做成job放到深夜或者专门时间,慢一点是可以理解的阿

而且日志不写对于数据以后的维护和恢复也是不利的

#16


哦,我是在数据维护的时候做这个操作,这个操作让用户干的话,我们的系统就完蛋了。因为我们的系统必须保持24小时绝对可用,晚上的用户也很多,我能在55个小时删除这几千万数据(循环一次删一条),但是有很大风险。所以想删除快一点,
呵呵。
                                langtian

#17


to:KnowLittle(人傻不要紧,只要肯学习。) 
你是对的,实在不行的话就只有关掉系统慢慢删,呵呵。

#18


关注·

#19


我认为可以选得到所有要删除的ID,这可从表DELETED表中得到
删除其它表则用WHERE Id in()就可以删除相应的记录啰

#20


楼上的想法不错
但是楼主的trigger不一定是如此简单的逻辑

#21


现在且不谈删除,我们来看看大容量复制对事务日志的操作:
使用完整恢复模式时,所有由 bcp 执行的行插入操作都记录在事务日志中。如果数据量较大,会造成事物日志迅速写满。为了防止事务日志耗尽空间,当符合以下全部条件时,可以执行最小日志记录的大容量复制: 
1、恢复模式是简单模式或大容量日志记录模式。
2、没有正在复制目标表。
3、目标表没有任何触发器。
4、目标表具有 0 行或没有索引。
任何不满足上述条件的SQL Server实例的大容量复制都将记入日志。
如果是按照这样的条件话,估计以上的删除操作(带触发器)再SQL中是不可能不写入日志的。

#22


笨辦法,先把不刪的資料拉到另外的表中,
再把原來的表資料全部刪除再倒入或
用另外的表替換原來的表,呵呵~
這個方法笨不笨~

#23


好像只能截断日志,而不能不记录日志。

学习。。。

#24


sql好像没什么好办法!
找盖茨问问!?
关注!

#25


你的问题其实是递归触发的问题,你可以从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


#26


sorry:

USE master0
EXEC sp_configure 'nested triggers', '0'
RECONFIGURE WITH OVERRIDE
 --Need restart SQL SERVER SERVICE

#27


呵~兩個豆豆的就是不一樣~收藏!

#28


那怎么不写日志呢??

#29


不写日志可能做不到。MSSQL没有这个选项。只有某些操作可以不写日志。
以前有个贴子讨论过这个问题。可以用select into将不删除的数据放到新表里去.(这个操作不写日志)然后用tuncate table (也不写日志)\drop table删除整原表)。这样可以日志少点。但是好不好很难说。

#30


按钮jj下午好!
还得让盖茨把这个功能完善一下!!哈哈!!

#31


exec sp_dboption yourDB,'trunc. log on chkpt.',true
就可以在INSERT,UPDATE,DELETE时不写日志了,

推荐阅读
author-avatar
桦林ye家伟
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有