某些 SQL 查詢在 ESXI 託管環境中執行得非常差
我們最近設置了一台具有 8 個雙核 CPU、20 GB RAM 和 3 個 1-TB 驅動器的新機器,這些驅動器設置在某種 RAID 中,導致我們實際使用了 2 個 1-TB 驅動器(我不是硬體人在這裡)。它被設置為 ESXi 主機,我們在其中設置了許多測試環境。目前的測試在 Windows 2003 64 位和 SQL Server 2005 Standard 64 位 SP3 上執行。從所有報告來看,該系統應該託管的環境比我們之前的設置執行得更好,但某些任務的執行情況要差得多。我發現了一個特定的 SQL 腳本,它在某些我無法理解的條件下可靠地執行得很慢。SQL 腳本是一系列簡單的 1700 多個 UPDATE 語句,開頭如下所示:
UPDATE SrfItem SET fkSrfItem = 5 WHERE id = 4 UPDATE SrfItem SET fkSrfItem = 8 WHERE id = 7 UPDATE SrfItem SET fkSrfItem = 10 WHERE id = 9
我發現,如果我在這些虛擬環境之一中遵循以下過程,執行腳本需要 9-12 秒:
測試案例 #1
- 從虛擬 SQL Server 環境中的備份還原測試數據庫
- 本地連接數據庫
- 執行腳本 - 此步驟需要 9 秒
我桌面上的相同程序在不到 1 秒的時間內執行了第 3 步。
測試案例 #2
- 從物理 SQL Server 環境中的備份還原測試數據庫
- 本地連接數據庫
- 執行腳本 - 此步驟不到 1 秒
但是在事務中執行腳本很快
測試案例 #3
- 從虛擬 SQL Server 環境中的備份還原測試數據庫
- 本地連接數據庫
- 在腳本開頭添加“BEGIN TRAN”
- 在腳本末尾添加“COMMIT TRAN”
- 執行腳本 - 此步驟不到 1 秒
我覺得有趣的是,即使我在事務中執行一次並回滾後它仍然執行緩慢
測試案例 #4
- 從虛擬 SQL Server 環境中的備份還原測試數據庫
- 本地連接數據庫
- 在腳本開頭添加“BEGIN TRAN”
- 在腳本末尾添加“ROLLBACK TRAN”
- 執行腳本 - 此步驟不到 1 秒
- 僅執行不包含事務的腳本部分 - 此步驟需要 9 秒。
我已經在具有 Windows 2003 32 位和 SQL 2005 32 位及以上的虛擬系統以及具有 Windows 2008 64 位和 SQL 2008 64 位的虛擬系統上執行測試。我已經在具有 Windows 2003 和 SQL 2005 的物理系統以及具有 Windows 7 64 位和 SQL 2008 R2 64 位的物理系統上執行測試。我嘗試過的所有虛擬系統都表現出這種緩慢,並且都託管在新的 ESXi 環境中。所有物理系統都沒有表現出這種緩慢性。
誰能幫我理解這裡發生了什麼?我擔心類似的性能問題會影響其他領域,我們應該在主機或來賓環境中重新配置一些東西。到目前為止,我們唯一能想到的是在主機的 BIOS 中關閉超執行緒,以匹配另一個虛擬環境及其主機的配置,我們無法看到緩慢的行為(我沒有觀察到其他不慢的虛擬環境和主機)。這會產生如此大的性能差異嗎?
**編輯:**在對我的問題和第一個答案進行一些審查之後,我同意我設法證明的可能是我們的物理環境和虛擬環境之間的 I/O 延遲性能的差異。我還意識到我應該提供一些其他細節:這些映像使用精簡配置,並且在它們下面有兩個或三個快照。這會對統計數據產生如此大的影響嗎?現在的問題是,這個統計數據在虛擬環境和物理環境之間存在如此巨大的差異是否正常?我應該能夠在環境或 SQL 配置中對其進行優化,還是由軟體本身為具有極端 I/O 延遲的虛擬系統編寫更優化的內容?
vSphere 客戶端報告虛擬磁碟上的寫入延遲為 11 到 40 毫秒,平均為 21 毫秒。這是一個有用的統計數據嗎?是不是很極端?
編輯: 我們的硬體(DL380 G6)似乎存在性能問題,如http://laez.nl/vmware-bad-performance-on-hp-proliant-dl380-g6-with-esxi-3-5-u4所述/我們只需要做一些重新配置來提高性能。我會接受這個答案,它引導我們朝著正確的方向看到磁碟 I/O 延遲是問題所在。
總結:
- 在您的真實伺服器上,您可以在不到一秒的時間內進行 1700 次表更新 + 1700 次送出,
- 在您的虛擬伺服器上,您可以在 9 秒內進行 1700 次表更新 + 1700 次送出,
- 在您的虛擬伺服器上,您可以在不到一秒的時間內完成 1700 次表更新 + 1 次送出。
因此,在我看來,您的問題可以重新定義為“在真實伺服器上,我可以在不到一秒的時間內進行 1700 次送出,但在我的虛擬伺服器上性能下降了十倍”。
1700 次表更新和 1700 次送出之間有什麼區別?表更新是完全記憶體的,完全不依賴於磁碟 I/O。對於送出,這是完全不同的。根據事務數據庫的本質,數據庫引擎必須確保在它開始送出下一個事務之前,送出實際上已經**保存到磁碟(保存到日誌文件)。**因此,對於這 1700 次送出中的每一次,它都必須等待整個 I/O 往返。綜上所述,在您的場景中,I/O 的延遲起著非常重要的作用,應該進行分析(不要將延遲與 I/O 速率或字節吞吐量混淆;這三個都是完全不同的動物;它們是總是單獨調整)。
使用 IOMeter 測試您的儲存是一個不錯的計劃。它在啟動時掛起,因為它試圖用它的測試文件填滿你的整個磁碟。只要等到文件增長到相當大的數量並重新啟動 IOMeter,它就會與“不完整”的測試文件一起正常工作。