2015-08-26 119 views
0

優化SQL代碼如何優化這些代碼在SQL與臨時表

INSERT INTO #ActivePlayers ([PlayerId]) 
     SELECT DISTINCT([OwnerSID]) [PlayerId]    
     FROM [WarehouseMgmt].[FactLoginTrans] FLT 
     JOIN [WarehouseMgmt].[DimPlayer] DP ON DP.[Id] = FLT.[OwnerSID] 
     WHERE [IsSystemUser]=0 
     AND [OwnerSID]>0 
     AND [WarehouseReports].[ConvertfromUTCtoTZ] (FLT.[LogonTime],@ZoneCode) BETWEEN DATEADD(month, -13, @Date) AND DATEADD(month, -1, @Date) 

什麼爲[WarehouseReports].[ConvertfromUTCtoTZ] (FLT.[LogonTime],@ZoneCode) BETWEEN DATEADD(month, -13, @Date) AND DATEADD(month, -1, @Date)最好的選擇,因爲這帶我一段時間,我在重複幾個SQL查詢,這條線。 如何把它放到臨時表中並在以後的查詢中使用它?

+0

既然'@ ZoneCode'是一個常量,而不是將'FLT.LogonTime'傳遞給每行的函數,您可以傳遞常量'@ Date',從而只調用一次該函數?或者,如果您發佈了定義,則可以將該函數轉換爲內聯表值函數,該函數比標量函數執行得更好。 – GarethD

+0

您可以替換表列上的ConvertFromUTCtoTZ以將DateAdd()值從TZ轉換爲UTC?在ConvertUTCToTZ(date1)和ConvertUtcToTZ(Date2)之間使用FLT.logonTime將使用Flt.LogonTime上的索引。 –

回答

-1

可能是你必須做類似的信息(警告,我寫元代碼,一定要檢查您的SQL服務器的文檔!)

ALTER TABLE [WarehouseMgmt].[FactLoginTrans] 
    ADD COLUMN BOOLEAN IsInPeriodOfInterest 

UPDATE [WarehouseMgmt].[FactLoginTrans] 
    SET IsInPeriodOfInterest = [WarehouseReports].[ConvertfromUTCtoTZ](FLT.[LogonTime], @ZoneCode) 
     BETWEEN DATEADD(month, -13, @Date) AND DATEADD(month, -1, @Date) 

,並改變你的進一步要求是指這個領域?

或者你可以,當然,

CREATE TEMPORARY TABLE (YOUR_PRIMARY_KEY, boolean IsInPeriodOfInterest) 
SELECT YOUR_PRIMARY_KEY, [WarehouseReports].[ConvertfromUTCtoTZ](FLT.[LogonTime],@ZoneCode) 
     BETWEEN DATEADD(month, -13, @Date) AND DATEADD(month, -1, @Date) 
    FROM [WarehouseMgmt].[FactLoginTrans] FLT 

,比與它一起。

+0

這既不是更有效率的,也不是好的做法(也是無效的語法,但你已經提出了一個警告)。在即席查詢中更新表以設置所需的字段甚至不是線程安全的。如果其他人在運行時用一半的時間運行類似的查詢,該怎麼辦?結果將是無稽之談。 – GarethD

+0

你說得對,添加一列是一個不好的習慣,sory。但是,如果數據庫在每個連接的基礎上支持它們,臨時表的情況將會起作用。如果其他進程在我們操作數據的同時修改數據,那麼無論如何我們都會產生不可預測的行爲。 – mickvav

2

要優化SQL查詢,您需要了解發生瓶頸的位置。閱讀How to analyse SQL Server performance

SQL優化最重要的因素是有一個SARG-able謂詞。換句話說,您的WHERE子句和JOIN必須能夠使用索引。就目前而言,您的查詢是無法修改的。需要[WarehouseMgmt].[DimPlayer]([Id])的索引,但我很確定你已經有一個。現在看看你的WHERE子句:

WHERE [IsSystemUser]=0 
AND [OwnerSID]>0 
AND [WarehouseReports].[ConvertfromUTCtoTZ] (FLT.[LogonTime],@ZoneCode) BETWEEN 
    DATEADD(month, -13, @Date) AND DATEADD(month, -1, @Date) 

這不能使用索引。前兩個條件可能因爲低廉的行爲而被丟棄(太多的行將被限定)。在日期範圍內留下範圍謂詞。通過要求將存儲的時區轉換爲參數時區,您可以放棄任何可能的優化查詢的機會,因爲UDF。你應該做相反:

  • 確保[LogonTime]是商店UTC(始終任何日期/時間存儲在數據庫中的UTC)
  • 轉換@date從用戶時區爲UTC:
    @utcdate = ConvertfromTZtoUTC] (@date,@ZoneCode)
  • 表達對[LogonTime]範圍:
    LogonTime BETWEEN DATEADD(month, -13, @utcdate) AND DATEADD(month, -1, @utcdate)
  • 具有覆蓋索引​​

開始閱讀Designing Indexes

將來,當詢問數據庫查詢時,請始終包含表的完整模式,包括所有索引。

+0

「'將用戶時區的@date轉換爲UTC, 表示[LogonTime]'的範圍''' – user2171512

+0

@ user2171512請參閱編輯 –