2

我想执行一条影响 1000 万行的更新语句。这是一个简单的更新,例如

UPDATE Table 
SET ColumnX = 0;

我确实注意到一个简单的SELECT喜欢

SELECT Column 
FROM Table

大约需要 34 秒。

由于它是生产中使用的表并且表相当大(2,8 GB 数据,索引 1,6 GB)我想在执行语句之前估计运行时间。

更新在 SQL Server 2008 R2 上执行。

是否有可能获得估计的运行时间?

4

4 回答 4

0

作为粗略估计,您可以尝试更新表格的一部分,然后使用数学计算整个时间。例如,更新前 100,000 行(表的 1/100),然后用该时间乘以 100,粗略估计整个表需要多长时间。唯一的问题是阻塞可能会使这个不准确(如果表的某些部分很少被访问,它们将比那些经常访问的部分更新得更快)。

最好的办法是使用循环一次更新表 X 行。

于 2014-12-03T15:01:22.293 回答
0

没有办法估计这一点。

你~可以~备份数据库,在类似的硬件上恢复它......然后尝试一下。但由于没有人可能会点击恢复的备份,即使这也不是一个精确的测量值。

如果您可以处理发生更新……但没有事务(也就是,某些行可以在几秒钟内具有正确的值……而其他行没有),那么我会邀请戈尔迪锁定方法。

Goldie Locks 将........不是一次点击中的所有行,但也不是逐行。

这是一个指针...更新TOP N ...

也许尝试 1,000 或 10,000 或类似的东西。

https://granadacoder.wordpress.com/2009/07/06/update-top-n-order-by-example/

...........

下面是一个修改后的例子。我有 1,000 行。我一次更新 100 行,所以它循环 10 次 (10 x 100 = 1000)...更新列。

这是一个“goldie locks”技巧............我认为这将在负载下的真实生产数据库上为您提供很好的服务。

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[Television]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
      BEGIN
            DROP TABLE [dbo].[Television]
      END
GO


CREATE TABLE [dbo].[Television] (
      TelevisionUUID [uniqueidentifier] not null default NEWSEQUENTIALID() ,
      TelevisionName varchar(64) not null ,
      TelevisionKey int not null ,
      IsCheckedOut bit default 0
)    
GO


ALTER TABLE dbo.Television ADD CONSTRAINT PK_Television_TelevisionUUID
PRIMARY KEY CLUSTERED (TelevisionUUID)
GO


ALTER TABLE dbo.Television ADD CONSTRAINT CK_Television_TelevisionName_UNIQUE
UNIQUE (TelevisionName)
GO


set nocount on

declare @counter int
select @counter = 11000
declare @currentTVName varchar(24)
declare @TopSize int
select @TopSize = 100

while @counter > 10000  /*  this loop counter is ONLY here for fake data,….do not use this syntax for production code */
begin

      select @currentTVName = 'TV:' + convert(varchar(24) , @counter)

      INSERT into dbo.Television ( TelevisionName , TelevisionKey ) values ( @currentTVName , @counter)

      select @counter = @counter - 1     
end


select count(*) as TV_Total_COUNT from dbo.Television


print ''
print 'Checked Out Items, Should be Zero at this point'
select count(*) as PRE_UPDATE_COUNT from dbo.Television tv where tv.IsCheckedOut <> 0


/*
--Does not Work!
Update TOP (10) dbo.Television
      Set IsCheckedOut = 1
FROM
      dbo.Television tv
ORDER BY tv.TelevisionKey
*/
declare @AuditTrail table ( TelevisionUUID uniqueidentifier , OldIsCheckedOut bit , NewIsCheckedOut bit )

declare @LoopCounter int
select @LoopCounter = 0

while exists ( Select top 1 * from dbo.Television tv where tv.IsCheckedOut = 0  )
BEGIN
            select @LoopCounter = @LoopCounter + 1
            /*print '/@LoopCounter/'
            print @LoopCounter
            print ''*/

                ;
                WITH cte1 AS      
                 (  SELECT
                      TOP (@TopSize)

                   TelevisionUUID , /* <<Note, the columns here must be available to the output */
                   IsCheckedOut       
                      FROM  
                            dbo.Television tv     
                    WITH ( UPDLOCK, READPAST , ROWLOCK ) --<<Optional Hints, but helps with concurrency issues  
                      WHERE 
                            IsCheckedOut = 0             
                      ORDER BY tv.TelevisionKey DESC       /* This order by is optional */
                )
                UPDATE cte1
                      SET  IsCheckedOut = 1
                output inserted.TelevisionUUID , deleted.IsCheckedOut , inserted.IsCheckedOut into @AuditTrail ( TelevisionUUID , OldIsCheckedOut , NewIsCheckedOut )
                ;
END

print '/Number of Update Loops/'
print @LoopCounter
print ''


print ''
print 'Newly Checked Out Items'
select count(*) as POST_UPDATE_COUNT from dbo.Television tv where tv.IsCheckedOut <> 0

print 'Output AuditTrail'
select * from @AuditTrail
print 'Not checked out items'
select count(*) as TVCOUNTIsNOTCheckedOut from dbo.Television tv where tv.IsCheckedOut = 0
于 2014-12-03T15:02:20.710 回答
0

我试着估计一个这样的更新

   DECLARE @i datetime
set @i=getdate()
DECLARE @t datetime

UPDATE dbo.EmployeeCity
SET City = 'dudi' -- varchar
where srno=1
set @t=getdate()

SELECT DATEDIFF(microsecond ,@i,@t) micro_sec
,      @i 'start'
,      @t 'end'

大多数时候我得到 3000 微秒

这绝对不是准确的唯一估计

在此处输入图像描述

于 2014-12-03T15:27:57.163 回答
-1

我想——不可能。但是,它必须比 SELECT 快(如果该列未包含在索引中)。

于 2014-12-03T14:55:25.360 回答