2010-01-04 99 views
9

當我第一次運行某個存儲過程時,大約需要2分鐘才能完成。當我第二次運行它時,它在大約15秒內完成。我假設這是因爲在第一次運行後所有內容都被緩存了。在我第一次運行此程序之前,是否可以「預熱緩存」?只有當我再次調用具有相同參數的存儲過程時,纔會使用緩存的信息,或者如果我使用不同的參數調用相同的存儲過程,是否會使用緩存的信息?SQL Server緩存問題

回答

9

當您執行查詢時,數據以塊的形式讀入內存。這些塊保留在內存中,但它們會「老化」。這意味着這些塊被標記爲上次訪問,並且當Sql Server需要另一個塊用於新查詢並且內存緩存已滿時,最近使用最少的塊(最早的塊)被踢出內存。 (在大多數情況下 - 全表掃描塊會立即老化以防止全表掃描超出內存並窒息服務器)。

這裏發生的事情是,在從第一查詢內存中的數據塊尚未被踢出的記憶卻又如此可用於你的第二個查詢,這意味着接盤,避免和性能的提高。

那麼你的問題是真正問的是「我能得到我需要到內存中的數據塊,而不讀取它們到內存(實際做一個查詢)?」。答案是否定的,除非你想緩存整個表,並讓它們永久駐留在內存中,從描述的查詢時間(以及數據大小)來看,這可能不是一個好主意。

你對性能的改善最好的辦法是看你的查詢執行計劃,看是否改變你的索引可能會給一個更好的結果。有跡象表明,可以在這裏提高性能的兩個主要方面:

  • 創建索引,其中查詢可以使用一個避免低效的查詢和全表掃描
  • 添加更多的列的索引,以避免第二盤讀取。例如,您有一個查詢返回列A和B,並在A和C上具有where子句,並且您在列A上有一個索引。您的查詢將使用列A的索引,要求讀取一個磁盤,但需要第二個磁盤命中以獲得列B和C.如果索引中包含所有列A,B和C,則可以避免第二個磁盤命中以獲取數據。
-1

即使使用不同的參數,執行計劃(您的過程的緩存信息)也會每次重複使用。這是使用存儲過程的好處之一。

第一次執行存儲過程時,SQL Server會生成執行計劃並將其放入過程高速緩存中。

數據庫的某些更改可能會觸發執行計劃的自動更新(並且您也可以明確要求重新編譯)。

執行計劃將根據其「年齡」從過程緩存中刪除。 (來自MSDN:很少被引用的對象很快就有資格取消分配,但實際上並沒有解除分配,除非其他對象需要內存。)

我不認爲有任何方法可以「加熱緩存」,除了執行存儲過程一次。這將保證高速緩存中有一個執行計劃,隨後的任何調用都會重用它。

更詳細的信息MSDN文檔中獲得:http://msdn.microsoft.com/en-us/library/ms181055(SQL.90).aspx

+4

您的回覆,但我看不出什麼毛病,不得要領。查詢編譯不需要1分45秒,所以這不是OP的問題。 OP緩存問題與數據頁緩存有關,而不是執行計劃緩存。 – erikkallen 2010-01-04 22:50:31

3

我不認爲生成執行計劃將花費更多的1秒。

我相信第一次和第二次運行之間的區別是由內存中的數據緩存引起的。

緩存中的數據可以被任何進一步的查詢(存儲過程或簡單選擇)重用。

您可以通過讀取相同數據的任何選擇來讀取數據來「加熱」緩存。但是,這甚至會花費大約90秒。

2

您可以檢查執行計劃以找出您的查詢使用哪些表和索引。然後,您可以執行一些SQL以將數據存入緩存,具體取決於您看到的內容。

  • 如果您看到聚簇索引seek,那麼可以簡單地執行SELECT * FROM my_big_table以強制所有表的數據頁進入高速緩存。
  • 如果看到非聚集索引搜索,則可以嘗試SELECT first_column_in_index FROM my_big_table

要強制加載特定索引,還可以在緩存熱身查詢中使用WITH(INDEX(index))表提示。