2012-05-15 101 views
1

我寫了一個腳本,需要大約15個小時才能執行。我需要一些查詢優化技術或建議,使這個腳本更快地... 如果有人可以幫助,採取對劇本一看:查詢需要優化

declare @max_date date 
declare @client_bp_id int 

Select @max_date=MAX(tran_date) from All_Share_Txn 

DELETE FROM Client_Share_Balance 

DECLARE All_Client_Bp_Id CURSOR FOR 
SELECT Bp_id FROM Client  --Take All Client's BPID 
    OPEN All_Client_Bp_Id 
    FETCH NEXT FROM All_Client_Bp_Id 
     INTO @client_bp_id 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 

    Insert Client_Share_Balance(Bp_id,Instrument_Id,Quantity_Total,Quantity_Matured,Quantity_Pledge,AVG_Cost,Updated_At,Created_At,Company_Id,Created_By,Updated_By) 
    select @client_bp_id,Instrument_Id, 
     sum(case when Is_buy='True' then Quantity when Is_buy='False' then -quantity end), --as Total Quantity 
     sum(case when Mature_Date_Share <= @max_date then (case Is_buy when '1' then quantity when '0' then -quantity end) else 0 end), --as Free Qty 
     ISnull((select sum(case pu.IsBuy when '1' then -pu.quantity else pu.quantity end) from 
      (Select * from Pledge UNION Select * from Unpledge) pu 
       where [email protected]_bp_id and pu.Instrument_Id=t1.Instrument_Id and pu.Txn_Date<[email protected]_date 
       group by pu.Client_Bp_id,pu.Instrument_Id),0), -- as Pledge_Quantity 
     dbo.Avg_Cost(@client_bp_id,Instrument_Id), --as Avg_rate 
     GETDATE(),GETDATE(),309,1,1 

    from All_Share_Txn t1 
    where [email protected]_bp_id and Instrument_Id is not null 
    group by Instrument_Id 
    having sum(case Is_buy when '1' then quantity when '0' then -quantity end)<> 0 
    or sum(case when Mature_Date_Share <= @max_date then (case Is_buy when '1' then quantity when '0' then -quantity end) else 0 end) <> 0 

    FETCH NEXT FROM All_Client_Bp_Id 
     INTO @client_bp_id 

END 

CLOSE All_Client_Bp_Id 
DEALLOCATE All_Client_Bp_Id 

只需要驗證,如果代碼可以寫更多有效..

+2

探索不用光標就可以重寫。這應該會提高性能很多。 – HardCode

+0

@ AbdurRahman-你試過[**這個答案**](http://stackoverflow.com/a/10606894/1379794)? – Nilish

回答

2
  1. 替換*你COLUMNNAMES Select * from Pledge。它應該像
    Select Instrument_Id from Pledge

  2. 排除遊標的使用。

  3. 您是否在PledgeUnpledge表中有獨特的記錄,如果是的話,應該使用UNION ALL。因爲它比UNION更快更多

  4. All_Share_Txn的記錄插入Local Temporary Table

  5. 創建另一個Local Temporary table,其中包含基於Instrument_Id列和Instrument_Id的字段「總量」信息。現在評估基於開關情況的條件並在此表中插入數量信息記錄。請注意,當你的這種情況下提取信息,請使用本地臨時表在第3步

  6. 創建另一個Local Temporary table這將對基於INSTRUMENT_ID柱和Instrument_Id領域「免費訂購數量」的信息創建的。現在評估基於開關情況的條件並在此表中插入Free Qty信息的記錄。請注意,當你的這種情況下提取信息,請使用本地臨時表在第3步

  7. 創建另一個Local Temporary table這將對基於INSTRUMENT_ID柱和Instrument_Id領域「Pledge_Quantity」信息創建的。現在評估基於開關情況的條件,並在此表中插入爲Pledge_Quantity信息。請注意,當你的這種情況下提取信息,請使用本地臨時表在第3步

  8. 創建另一個Local Temporary table這將對基於INSTRUMENT_ID柱和Instrument_Id領域「Avg_rate」信息創建的。現在評估基於開關情況的條件,並在此表中插入記錄 爲Avg_rate信息。請注意,在提取此上下文的信息時,請使用在步驟3中創建的本地臨時表。

  9. 現在,藉助於步驟3,4,5,6,7中創建的表之間的聯接。可以立即獲取結果集。

+0

太多臨時表..它需要這麼多表嗎..?無論如何+1爲您的答案.. –

2

如果我理解你的代碼。光標是代碼中的瓶頸。所以我會跳過光標,做這樣的事情:

Insert Client_Share_Balance(Bp_id,Instrument_Id..) 
select Client_Bp_id, 
...... 
from All_Share_Txn t1 
where EXISTS(SELECT NULL FROM Client WHERE Client_Bp_id=t1.Bp_id) 
and Instrument_Id is not null 
group by Instrument_Id,Client_Bp_id 
....... 
+0

謝謝..這似乎更方便..我試圖按照您的建議實施我的代碼..如果它提高性能我會接受您的答案..再次感謝.. +1爲您的答案.. –

+0

沒問題。很高興幫助:P – Arion

+0

它提高了性能..現在查詢需要5個小時執行..但我認爲它可以更快..如果有任何其他建議..請給我.. –

0

除非你不在乎,你正在閱讀提交的數據,那麼你可以告訴SQL Server看數據事情是這樣的,沒有持有的對象的任何鎖...基本上相同的行爲WITH(NOLOCK ),但Microsoft建議不要使用對象提示,並讓SQL Server決定使用最佳鎖定方法。沒有「擔心」數據被提交或不提交,這大大加速了數據的提取。

添加到您查詢的頂部

SET事務隔離級別未提交讀 - 設爲在連接級別,不是一次性的事情 GO

See this link TRANSACTION ISOLATION LEVEL

接下來的事情,請檢查您的唯一ID列是否具有羣集索引。如果他們只有獨特的約束,那麼仍然會留下一堆,而不是一張桌子。堆基本上是一團糟。 (你可能知道這個東西,只是提及它)接下來,確保你在WHERE ORDER BY GROUP HAVING ...中使用的所有列都有非聚集索引,並且包含經常返回的列;這消耗更多的磁盤空間btw。如果使用的是Enterprise Version或更高版本,請使用壓縮索引和表格。

我會在表上運行帶有FULLSCAN的UPDATE STATISTICS來爲SQL Server提供最新和最好的統計數據。重建聚集索引會順便爲你做,並且你可以告訴只更新數據統計信息,以幫助加快這個過程,因爲如果你的表是數百萬行,那麼可能需要一些時間。

您正在採取的最大性能是您正在對聚合結果進行分組。 SQL Server正在掃描,使用工作表,排序...所有東西,但尋求索引,所有因爲沒有索引可用於幫助您的GROUP BY,HAVING等..

有時我們沒有選擇這個問題,但有一些技巧,比如創建一個臨時表(或者表對象,是的,你可以在兩者上創建索引)並用預先計算的結果填充它,確保這個臨時表可以加入。當你使用ORDER BY,GROUP BY,HAVING時,除非你使用的是一列,或者多列,並使用像SUM或標量值用戶定義的函數那樣的聚合,否則它會很慢 - 取決於你定義的緩慢:)但你確實聲明你認爲它應該更快。

一些基本的設置,看看在SQL Server的任何實例:

  1. tempdb中應該有相同數量的文件,你有核,大小相同,所有使用MB相同的增長速度,不是%。如果您擁有8個以上的內核,我只能上傳8個文件。進行更改後重新啓動實例;你確實需要但我推薦它。

    示例:12個核心。

    tempdb.mdf  size= 1024MB growby= 256MB 
    tempdb2.ndf size= 1024MB growby= 256MB 
    (etc) 
    tempdb8.ndf size= 1024MB growby= 256MB 
    
  2. 與您的數據庫一樣。如果您需要添加更多文件,那麼使用建議的大小設置並重建所有聚簇索引,這將在文件間傳播數據,因爲它將重建數據的物理結構。

  3. 不要讓SQL Server佔用所有內存!將其限制值設置爲total_avail_phys_memory減去2GB(將O/S保留在內存中)

  4. 不要只使用PRIMARY FILE GROUP;將您的數據和索引分隔到自己的文件組中。如果可以的話,將索引放置在RAID 10驅動器上,並將數據放在RAID 5或RAID 6上。

  5. 確保您通過維護計劃或滾動來爲SQL Server用戶數據庫提供所需的定期維護你自己的腳本。

  6. 對RAID 5的數據,對RAID 10日誌,臨時數據庫上RAID 10 - 每個LUN(驅動器號)應該有專門的主軸(驅動器)

我希望這些建議都是有幫助的,如果有的話,他們應該有助於實例的整體性能。