我正在使用以下执行1'500'000行
我的SP如下:
CREATE Procedure USP_12(@AuditMasterID as varchar(10),@TABLE as Varchar(50))
as
BEGIN
Declare @SQLStatement varchar(2000)
Declare @PrefixNo varchar(20)
Declare @PrefixLen varchar(20)
Declare @AfterPrefixLen varchar(20)
DECLARE Cur_Prefix CURSOR
FOR
SELECT PrefixNo,PrefixLen,AfterPrefixLen FROM NoSeriesMaster_Prefix WHERE PrefixType='SMS' order by ID
OPEN Cur_Prefix
FETCH NEXT FROM Cur_Prefix INTO @PrefixNo,@PrefixLen,@AfterPrefixLen
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQLStatement = 'update '+@TABLE+' set AuditData.TATCallType=''12'', AuditData.TATCallUnit=''1'' ' +
'from '+@TABLE+' AuditData '+
'inner join AuditMaster am on am.ID=AuditData.AuditMaster_ID '+
'inner join HomeCircleMaster hcm on hcm.Ori_CircleMaster_ID=am.CircleMaster_ID and hcm.Ori_ServiceTypeMaster_ID=1 and hcm.Dest_ServiceTypeMaster_ID=1 '+
'inner join AuditTaggingMaster atm on atm.AuditMaster_ID=am.ID '+
'inner join NoSeriesMaster ns on (ns.CircleMaster_ID=am.CircleMaster_ID or ns.CircleMaster_ID=hcm.Dest_CircleMaster_ID) '+
' and ns.ProviderMaster_ID=am.ProviderMaster_ID '+
' and ns.ServiceTypeMaster_ID=1 '+
'inner join ProviderMaster_CallTypeMaster pm_ctm on pm_ctm.ProviderMaster_ID=am.ProviderMaster_ID and pm_ctm.CallTypeMaster_ID=101 and pm_ctm.CallTypeTagValue=AuditData.CallTypeTag '+
'where AuditData.TATCallType is null and substring(AuditData.CallTo,1,convert(int,'+@PrefixLen+'))='''+ @PrefixNo + ''' and len(AuditData.CallTo)='+convert(varchar(10),convert(int,@PrefixLen)+convert(int,@AfterPrefixLen))+' and '''+@PrefixNo+'''+ns.NoSeries=Left(AuditData.CallTo,len(ns.NoSeries)+convert(int,'+@PrefixLen+')) and AuditData.AuditMaster_ID='+@AuditMasterID+' '
print(@SQLStatement)
exec(@SQLStatement)
FETCH NEXT FROM Cur_Prefix INTO @PrefixNo,@PrefixLen,@AfterPrefixLen
END
CLOSE Cur_Prefix
DEALLOCATE Cur_Prefix
end
以上查询需要60分钟才能对1'500'000行
运行该查询是否可以进行任何优化?
答案 0 :(得分:3)
没有。 1优化 - 摆脱CURSOR! :-)你对许多不同的表执行此操作吗?你能以某种方式摆脱@table变量吗?
将动态SQL与游标结合起来是一种可靠的方法来消除SQL Server可能使用的任何优化.......
尝试针对该1.5mio表运行存储过程的核心,表名为hardcoded:
update (your table name)
set AuditData.TATCallType='12', AuditData.TATCallUnit='1'
from (your table name) AuditData
inner join AuditMaster am on am.ID=AuditData.AuditMaster_ID
...... (and so forth)
这需要多长时间?
你可以发布更多信息吗?表格结构,可用的指数是什么?
马克
PS:我尝试分解庞大的SQL语句,并尝试通过公用表表达式来避免使用CURSOR。然而,这需要您将@Table名称硬编码到您的语句中 - 这对您有用吗?
试试吧 - 你现在几点钟了?
UPDATE
(your table name)
SET
AuditData.TATCallType='12', AuditData.TATCallUnit='1'
FROM
(your table name) AuditData
INNER JOIN
AuditMaster am ON am.ID = AuditData.AuditMaster_ID
INNER JOIN
HomeCircleMaster hcm ON hcm.Ori_CircleMaster_ID = am.CircleMaster_ID
AND hcm.Ori_ServiceTypeMaster_ID = 1
AND hcm.Dest_ServiceTypeMaster_ID = 1
INNER JOIN
AuditTaggingMaster atm ON atm.AuditMaster_ID = am.ID
INNER JOIN
NoSeriesMaster ns on (ns.CircleMaster_ID = am.CircleMaster_ID or ns.CircleMaster_ID = hcm.Dest_CircleMaster_ID)
AND ns.ProviderMaster_ID = am.ProviderMaster_ID
AND ns.ServiceTypeMaster_ID = 1
INNER JOIN
ProviderMaster_CallTypeMaster pm_ctm ON pm_ctm.ProviderMaster_ID = am.ProviderMaster_ID
AND pm_ctm.CallTypeMaster_ID = 101
AND pm_ctm.CallTypeTagValue = AuditData.CallTypeTag
INNER JOIN
NoSeriesMaster_Prefix PD ON SUBSTRING(AuditData.CallTo, 1, CONVERT(INT, PD.PrefixLen)) = PD.PrefixNo
AND LEN(AuditData.CallTo) = CONVERT(VARCHAR(10), CONVERT(INT, PD.PrefixLen) + CONVERT(INT, PD.AfterPrefixLen))
AND PD.PrefixNo + ns.NoSeries = LEFT(AuditData.CallTo, len(ns.NoSeries) + CONVERT(INT, PD.PrefixLen))
WHERE
AuditData.TATCallType is NULL
AND AuditData.AuditMaster_ID = @AuditMasterID
AND PD.PrefixType = 'SMS'
IF 这是有效的,接下来的步骤是检查您是否有
的索引所有的JOIN条件,例如
INNER JOIN AuditTaggingMaster atm ON atm.AuditMaster_ID = am.ID
你有关于“atm.AuditMaster_ID”和“am.ID”的索引吗?
你的WHERE子句(例如你有PD.PrefixType的索引吗?)
此外,对于每种情况,您都需要考虑索引的选择性。例如,在PD.PrefixType ='SMS'的WHERE子句中 - 这是选择“PD”表中所有条目的一半,还是仅1-2%?如果索引是选择性的,那么它很可能会被使用 - 如果它在一个“BIT”列上,它只能有两个值,每个值将选择大约一半的表,不要在那里放一个索引,它赢了没帮忙。
答案 1 :(得分:2)
由于你正在传递@table,你似乎最好为你需要运行它的每个表都有一个sProc。至少服务器与缓存计划有争斗的机会。
答案 2 :(得分:1)
我要检查的第一件事是我已经在所有外键上定义了索引。
在点击审核表时,阻止也可能是一个严重的问题。阅读表格提示,看看他们是否可以帮助解决因阻塞造成的任何延迟。