2009-07-13 43 views
0

IM使用其下面執行鍼對1'500'000行優化SQL查詢

我的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 '[email protected]+' set AuditData.TATCallType=''12'', AuditData.TATCallUnit=''1'' ' + 
'from '[email protected]+' 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,'[email protected]+'))='''+ @PrefixNo + ''' and len(AuditData.CallTo)='+convert(varchar(10),convert(int,@PrefixLen)+convert(int,@AfterPrefixLen))+' and '''[email protected]+'''+ns.NoSeries=Left(AuditData.CallTo,len(ns.NoSeries)+convert(int,'[email protected]+')) and AuditData.AuditMaster_ID='[email protected]+' ' 
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行

該查詢是否有可能的優化?

請幫我迫切其

thanx提前...

+1

也許你能幫我們幫助你做一個最小的分析*爲什麼*會這麼慢。查詢計劃,統計IO,某事。 SQL是一種聲明性語言,如果速度緩慢或者速度很慢,你永遠無法通過查看文本來說明。重要的是實際的執行計劃,並且我們不可能猜測沒有了解您的模式或沒有看到一些執行統計數據的計劃。 – 2009-07-13 16:28:50

+0

在其中一個緩慢的@Table中分離一個UPDATE,在SSMS中運行它並提取計劃。這裏的帖子是執行計劃。 – 2009-07-13 16:29:33

+0

使用更上級篇DBA,MySQL等 – nerkn 2011-03-29 11:15:42

回答

3

1號optimzation - 擺脫光標! :-)你是否對許多不同的表執行此操作?你能以某種方式擺脫@table變量嗎?

結合動態SQL與遊標是一種安全可靠的方式殺死任何優化SQL Server可能已經能夠使用.......

嘗試運行鍼對您的存儲過程的核心1.5mio表,硬編碼表格名稱:

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語句,並試圖通過一個公用表表達式的方式,以避免光標。然而,這需要您將@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你需要運行它的每個表。至少服務器將有與緩存計劃戰鬥的機會。