關鍵字:SQL性能 方法
避免LEFTJOIN和NULL
當然,有很多時候您需要執行LEFTJOIN和使用NULL值。但是,它們并不適用于所有情況。改變SQL查詢的構建方式可能會產生將一個花幾分鐘運行的報告縮短到只花幾秒鐘這樣的天壤之別的效果。有時,必須在查詢中調整數據的形態,使之適應應用程序所要求的顯示方式。雖然TABLE數據類型會減少大量占用資源的情況,但在查詢中還有許多區域可以進行優化。SQL的一個有價值的常用功能是LEFTJOIN。它可以用于檢索第一個表中的所有行、第二個表中所有匹配的行、以及第二個表中與第一個表不匹配的所有行。例如,如果希望返回每個客戶及其定單,使用LEFTJOIN則可以顯示有定單和沒有定單的客戶。
此工具可能會被過度使用。LEFTJOIN消耗的資源非常之多,因為它們包含與NULL(不存在)數據匹配的數據。在某些情況下,這是不可避免的,但是代價可能非常高。LEFTJOIN比INNERJOIN消耗資源更多,所以如果您可以重新編寫查詢以使得該查詢不使用任何LEFTJOIN,則會得到非?捎^的回報。
加快使用LEFTJOIN的查詢速度的一項技術涉及創建一個TABLE數據類型,插入第一個表(LEFTJOIN左側的表)中的所有行,然后使用第二個表中的值更新TABLE數據類型。此技術是一個兩步的過程,但與標準的LEFTJOIN相比,可以節省大量時間。一個很好的規則是嘗試各種不同的技術并記錄每種技術所需的時間,直到獲得用于您的應用程序的執行性能最佳的查詢。
測試查詢的速度時,有必要多次運行此查詢,然后取一個平均值。因為查詢(或存儲過程)可能會存儲在SQLServer內存中的過程緩存中,因此第一次嘗試耗費的時間好像稍長一些,而所有后續嘗試耗費的時間都較短。另外,運行您的查詢時,可能正在針對相同的表運行其他查詢。當其他查詢鎖定和解鎖這些表時,可能會導致您的查詢要排隊等待。例如,如果您進行查詢時某人正在更新此表中的數據,則在更新提交時您的查詢可能需要耗費更長時間來執行。
避免使用LEFTJOIN時速度降低的最簡單方法是盡可能多地圍繞它們設計數據庫。例如,假設某一產品可能具有類別也可能沒有類別。如果Products表存儲了其類別的ID,而沒有用于某個特定產品的類別,則您可以在字段中存儲NULL值。然后您必須執行LEFTJOIN來獲取所有產品及其類別。您可以創建一個值為“NoCategory”的類別,從而指定外鍵關系不允許NULL值。通過執行上述操作,現在您就可以使用INNERJOIN檢索所有產品及其類別了。雖然這看起來好像是一個帶有多余數據的變通方法,但可能是一個很有價值的技術,因為它可以消除SQL批處理語句中消耗資源較多的LEFTJOIN。在數據庫中全部使用此概念可以為您節省大量的處理時間。請記住,對于您的用戶而言,即使幾秒鐘的時間也非常重要,因為當您有許多用戶正在訪問同一個聯機數據庫應用程序時,這幾秒鐘實際上的意義會非常重大。
靈活使用笛卡爾乘積
對于此技巧,我將進行非常詳細的介紹,并提倡在某些情況下使用笛卡爾乘積。出于某些原因,笛卡爾乘積(CROSSJOIN)遭到了很多譴責,開發人員通常會被警告根本就不要使用它們。在許多情況下,它們消耗的資源太多,從而無法高效使用。但是像SQL中的任何工具一樣,如果正確使用,它們也會很有價值。例如,如果您想運行一個返回每月數據(即使某一特定月份客戶沒有定單也要返回)的查詢,您就可以很方便地使用笛卡爾乘積。圖2中的SQL就執行了上述操作。
雖然這看起來好像沒什么神奇的,但是請考慮一下,如果您從客戶到定單(這些定單按月份進行分組并對銷售額進行小計)進行了標準的INNERJOIN,則只會獲得客戶有定單的月份。因此,對于客戶未訂購任何產品的月份,您不會獲得0值。如果您想為每個客戶都繪制一個圖,以顯示每個月和該月銷售額,則可能希望此圖包括月銷售額為0的月份,以便直觀標識出這些月份。如果使用圖2中的SQL,數據則會跳過銷售額為0美元的月份,因為在定單表中對于零銷售額不會包含任何行(假設您只存儲發生的事件)。
圖3中的代碼雖然較長,但是可以達到獲取所有銷售數據(甚至包括沒有銷售額的月份)的目標。首先,它會提取去年所有月份的列表,然后將它們放入第一個TABLE數據類型表(@tblMonths)中。下一步,此代碼會獲取在該時間段內有銷售額的所有客戶公司的名稱列表,然后將它們放入另一個TABLE數據類型表(@tblCus-tomers)中。這兩個表存儲了創建結果集所必需的所有基本數據,但實際銷售數量除外。第一個表中列出了所有月份(12行),第二個表中列出了這個時間段內有銷售額的所有客戶(對于我是81個)。并非每個客戶在過去12個月中的每個月都購買了產品,所以,執行INNERJOIN或LEFTJOIN不會返回每個月的每個客戶。這些操作只會返回購買產品的客戶和月份。
文章來源于領測軟件測試網 http://www.kjueaiud.com/