我正在我们的生产数据库上运行一个脚本,它有两个表:我们的用户表(其中3700个)和他们所做的引用表(280000个)。 Quote是我们应用程序中的主要对象,一个非常大的对象,为其创建和填充了许多数据表。我的目标是从所有引号清除数据库,但是由一小组用户组成。
我首先创建一个临时表,其中包含这些用户的id(在脚本中也使用了其他用户),然后是一个游标,它通过主表运行引号,列出了它们,以及那些从中创建的引号用户组进行必要的清理。
我看到这个脚本将被执行大约26个小时,我认为这是特殊的,因为我需要大约15分钟来恢复数据库,我想那里最重的sql被执行了。然而,数据库的重量超过100GB。
脚本的某些部分是否非常不合理,或者您有一些建议如何通过更短的执行来完成此操作。
我们正在运行SQL Server 2008 R2。
这是剧本的草图。
CREATE table #UsersIdsToStay(user_id int)
INSERT INTO #UsersIdsToStay
select user_id
from users
where user_name like '%SOMESTRING '
-----
declare @QuoteId int
declare @UserId int
declare QuoteCursor cursor for
select DISTINCT QuoteId, UserId
from QuotesTable
where UserId not in
(
select * from #UsersIdsToStay
)
open QuoteCursor
while 1=1
begin
fetch QuoteCursor into @QuoteId, @UserId
if @@fetch_status != 0 break
-- all the deletions from related tables are executed here using @QuoteId and @UserId
exec('delete from QuoteHistory where QuoteId = ' + @QuoteId + ' and UserId = ' + @UserId )
exec('delete from QuoteRevisions where QuoteId = ' + @QuoteId + ' and UserId = ' + @UserId )
exec('delete from QuoteItems where QuoteId = ' + @QuoteId + ' and UserId = ' + @UserId )
....
end
close QuoteCursor;
deallocate QuoteCursor
答案 0 :(得分:1)
光标限制您在每个相关表上一次只删除一个User_Id / Quote_Id组合。通过使用连接,您将能够大量删除。
您还可以使用公用表表达式(CTE)切换临时表。如果这是一个一次性脚本,临时表应该没问题,但对于生产代码,我会创建一个CTE。
if OBJECT_ID('tempdb..#quotesToDelete') is not null
drop table #quotesToDelete
select distinct
ut.user_id,
qt.quote_id
into #quotesToDelete
from dbo.QuotesTable qt (nolock)
inner join dbo.UsersTable ut (nolock)
on qt.user_id = ut.user_id
where ut.user_name not like '%SOMESTRING '
-- all the deletions from related tables are executed here using @QuoteId and @UserId
-- relatedtableA
delete a
from relatedtableA a
inner join #quotesToDelete b
on a.user_id = b.user_id
and a.quote_id = b.quote_id
-- relatedtableB
...
答案 1 :(得分:0)
由于您没有显示删除,因此无法向您展示如何避免光标。
但是如果没有临时性的话,可以做到这一点
select DISTINCT QuoteId, UserId
from QuotesTable
where UserId not in
(
select user_id
from users
where user_name like '%SOMESTRING '
)
或
select DISTINCT QuoteId, UserId
from QuotesTable
left join UserId
on UserId.user_id = QuotesTable.UserId
and user_name like '%SOMESTRING '
where UserId.user_id is null
问题是cusor,你不需要它
CREATE table #QuotesToDelete(QuoteId int, UserID int)
insert into #QuotesToDelete
select DISTINCT QuoteId, UserId
from QuotesTable
left join UserId
on UserId.user_id = QuotesTable.UserId
and user_name like '%SOMESTRING '
where UserId.user_id is null
delete QH
from QuoteHistory QH
join #QuotesToDelete
on #QuotesToDelete.QuoteId = QH.QuoteId
and #QuotesToDelete.UserID = QH.UserID
delete QR
from QuoteRevisions QR
join #QuotesToDelete
on #QuotesToDelete.QuoteId = QR.QuoteId
and #QuotesToDelete.UserID = QR.UserID