我想执行影响1000万行的更新声明。这是一个简单的更新,如
UPDATE Table
SET ColumnX = 0;
我注意到一个简单的SELECT
喜欢
SELECT Column
FROM Table
需要大约34秒。
因为它是生产中使用的表,并且表格相当大(2,8 GB数据,索引1,6 GB),我想在执行语句之前估计运行时。
更新在SQL Server 2008 R2上执行。
是否有可能获得估计的运行时间?
答案 0 :(得分:0)
粗略估计,您可以尝试更新表格的一小部分,然后使用数学计算整个时间。例如,更新排名前100,000的行(表格的1/100),然后将该时间乘以100得到粗略估计全表将花费多长时间。唯一的问题是阻塞可能导致这种情况不准确(如果表中很少有部分访问它们,它们的更新速度会比经常访问的速度快得多)。
最好的办法是使用循环一次更新表X行。
答案 1 :(得分:0)
无法估计这一点。
你可以〜备份数据库,在类似的硬件上恢复它......然后尝试。但是,由于没有人可能会进行恢复备份,即使这不是一个精确的测量。
如果您可以处理更新发生....但没有事务(也就是说,某些行可以在几秒钟内获得正确的值,而其他行没有),那么我会邀请goldie lock方法。
Goldie Locks将........不是所有行中的一行,而是一行一行。
这是一个指针...更新TOP N ...
也许尝试1,000或10,000或类似的东西。
https://granadacoder.wordpress.com/2009/07/06/update-top-n-order-by-example/
........
以下是修改后的示例。我有1000行。 我一次更新100行,所以它循环10次(10 x 100 = 1000)...来更新列。
这是一个“黄金锁定”技巧..........我认为这对你在负载下的真实生产数据库有用。
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
答案 2 :(得分: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微秒
这绝对不是唯一的估计
答案 3 :(得分:-1)
我想 - 没办法。但是,它必须比SELECT快(如果列中没有包含索引)。