【學習筆記】高性能MySQL(第三版)——第2章:MySQL基准測試
基准測試(benchmark)是MySQL新手和專家都需要掌握的一項基本技能。簡單地說,基准測試是針對系統設計的一種壓力測試。通常的目標是為了掌握系統的行為。但也有其他原因,如重現某個系統狀態,或者做新硬件的可靠性測試。
2.1 為什麼需要基准測試
基准測試是唯一方便有效的、可以學習系統在給定的工作負載下會發生什麼的方法。 基准測試可以觀察系統在不同壓力下的行為,評估系統的容量,掌握哪些是重要的變化,或者觀察系統如何處理不同的數據。 基准測試可以在系統實際負載之外創造一些虛構場景進行測試。還可以用於其它目的,比如為應用創建單元測試套件。 基准測試的一個主要問題在於其不是真實壓力的測試。 基准測試只能進行大概的測試,來確定系統大致的余量有多少。當然也可以做一些真實壓力測試(和基准測試有區別),但在構造數據集和壓力的時候要特別小心,而且這樣就不再是基准測試了。基准測試要盡量簡單直接,結果之間容易相互比較,成本低且易於執行。盡管有諸多限制,基准測試還是非常有用的(只要搞清楚測試的原理,並且了解如何分析結果所代表的意義)。
2.2 基准測試的策略
基准測試有兩種主要的策略:一是針對整個系統的整體測試,另外是單獨測試MySQL。這兩種策略也被稱為集成式(full-stack)以及單組件式(single-component)基准測試。
2.2.1 測試何種指標
在開始執行甚至是在設計基准測試之前,需要先明確測試的目標。測試目標決定了選擇什麼樣的測試工具和技術,以獲得精確而有意義的測試結果。
考慮以下指標,選擇如何滿足測試的需求
吞吐量
吞吐量指的是單位時間內的事務處理數。這一直是經典的數據庫應用測試指標。這類基准測試主要針對在線事務處理(OLTP)的吞吐量,非常適用於多用戶的交互式應用。常用的測試單位是每秒事務數(TPS),有些也采用每分鐘事務數(TPM)。
響應時間或者延遲
這個指標用於測試任務所需的整體時間。根據具體的應用,測試的時間單位可能是微秒、毫秒、秒或分鐘。根據不同的時間單位可以計算出平均響應時間、最小響應時間、最大響應時間和所占百分比。最大響應時間通常意義不大,因為測試時間越長,最大響應時間也可能越大。而且其結果通常不可重復,每次測試都可能得到不同的最大響應時間。因此,通常可以使用百分比響應時間(percentile response time)來替代最大響應時間。
並發性
並發性是一個非常重要又經常被誤解和誤用的指標。例如,它經常被表示成多少用戶在同一時間浏覽一個Web站點,經常使用的指標是有多少個會話。然而,HTTP協議是無狀態的,大多數用戶只是簡單地讀取浏覽器上顯示的信息,這並不等同於Web服務器的並發性。而且,Web服務器的並發性也不等同於數據庫的並發性,而僅僅只表示會話存儲機制可以處理多少數據的能力。Web服務器的並發性更准確的度量指標,應該是在任意時間有多少同時發生的並發請求。
在應用的不同環節都可以測試響應的並發性。Web服務器的高並發,一般也會導致數據庫的高並發,但服務器采用的語言和工具集對此都會有影響。注意不要將創建數據庫連接和並發性搞混淆。一個設計良好的應用,同時可以打開成百上千個MySQL數據庫服務器連接,但可能同時只有少數連接在執行查詢。所以說,一個Web站點“同時有50000個用戶”訪問,卻可能只有10~15個並發請求到MySQL數據庫。
換句話說,並發性基准測試需要關注的是正在工作中的並發操作,或者是同時工作中的線程數或者連接數。當並發性增加時,需要測試吞吐量是否下降,響應時間是否變長,如果是這樣,應用可能就無法處理峰值壓力。
並發性的測量完全不同於響應時間和吞吐量。它不像是一個結果,而更像是設置基准測試的一種屬性。並發性測試通常不是為了測試應用能達到的並發度,而是為了測試應用在不同並發下的性能。當然,數據庫的並發性還是需要測量的。可以通過sysbench指定32、64或128個線程的測試,然後在測試期間記錄MySQL數據庫的Threads_running狀態值。
可擴展性
在系統的業務壓力可能發生變化的情況下,測試可擴展性就非常必要了。簡單地說,可擴展性指的是,給系統增加一倍的工作,在理想情況下就能獲得兩倍的結果(即吞吐量增加一倍)。或者說,給系統增加一倍的資源(比如兩倍的CPU數),就可以獲得兩倍的吞吐量。當然,同時性能(響應時間)也必須在可以接受的范圍內。大多數系統是無法做到如此理想的線性擴展的。隨著壓力的變化,吞吐量和性能都可能越來越差。
可擴展性指標對於容量規范非常有用,它可以提供其他測試無法提供的信息,來幫助發現應用的瓶頸。
歸根結底,應該測試那些對用戶來說最重要的指標。因此應該盡可能地去收集一些需求,比如,什麼樣的響應時間是可以接受的,期待多少的並發性,等等。然後基於這些需求來設計基准測試,避免目光短淺地只關注部分指標,而忽略其他指標。
2.3 基准測試方法
以下常見錯誤可能導致測試結果無用或者不精確
1. 使用真實數據的子集而不是全集。
2. 使用錯誤的數據分布。
3. 使用不真實的分布參數。
4. 在多用戶場景中,只做單用戶的測試。
5. 在單服務器上測試分布式應用。
6. 與真實用戶行為不匹配。
7. 反復執行同一個查詢。
8. 沒有檢查錯誤。基准測試完成後,一定要檢查一下錯誤日志,這應該是基本的要求。
9. 忽略了系統預熱(warm up)的過程。
10. 使用默認的服務器配置。
11. 測試時間太短。
如果其他條件相同,就應努力使測試過程盡可能地接近真實應用的情況。
2.3.1 設計和規劃基准測試
規劃基准測試的第一步是提出問題並明確目標。然後決定是采用標准的基准測試,還是設計專用的測試。 如果采用標准的基准測試,應該確認選擇了合適的測試方案。 設計專用的基准測試是很復雜的,往往需要一個迭代的過程。首先需要獲得生產數據集的快照,並且該快照很容易還原,以便進行後續的測試。然後,針對數據運行查詢。可以建立一個單元測試集作為初步的測試,並運行多遍。
但是這和真實的數據庫環境還是有差別的。更好的辦法是選擇一個有代表性的時間段,記錄生產系統上的所有查詢。如果時間段選得比較小,則可以選擇多個時間段。這樣有助於覆蓋整個系統的活動狀態。 可以在不同級別記錄查詢。如果是集成式(full-stack)基准測試,可以記錄Web服務器上的HTTP請求,也可以打開MySQL的查詢日志(Query Log)。倘若要重演這些查詢,就要確保創建多線程來並行執行,而不是單個線程線性地執行。對日志中的每個連接都應該創建獨立的線程,而不是將所有的查詢隨機地分配到一些線程中。查詢日志中記錄了每個查詢是在哪個連接中執行的。 即使不需要創建專用的基准測試,詳細地寫下測試規劃也是必需的。測試可能要多次反復運行,因此需要精確地重現測試過程,而且也要考慮到下次測試不是同一個人的情況。 應該建立將參數和結果文檔化的規范,每一輪測試都必須進行詳細記錄。
需要記住的是,經常要寫一些腳本來分析測試結果,因此如果能夠不用打開文檔等額外操作,當然是更好的。
2.3.2 基准測試應該運行多長時間
基准測試應該運行足夠長的時間,這一點很重要。有時候無法確認測試需要多長的時間才足夠,如果這樣可以讓測試一直運行,持續觀察直到確認系統已經穩定。
一個簡單的測試規則,就是等系統看起來穩定的時間至少等於系統預熱的時間。 一個常見的錯誤的測試方式是,只執行一系列短期的測試,例如每次60秒的測試,就在此基礎上去總結系統的性能。如果不能自己進行長時間的測試,與其用短時間的測試結果來評斷,不如參考別人的測試結果。
擴展基准測試的I/O性能圖
2.3.3 獲取系統性能和狀態
在執行基准測試時,需要盡可能多地手機被測試系統的信息。使用shell腳本,盡可能多的收集數據,多余一些數據總比缺乏重要的數據要好。需要記錄的數據包括系統狀態和性能指標。 先收集所有的原始數據,然後再基於此做分析和過濾是一個好習慣。如果在收集的時候就對數據做預處理,而後續分析發現一些異常的地方需要用到更多的原始數據,就“抓瞎”了。
2.3.4 獲得准確的測試結果
獲得准確測試結果的最好辦法,是回答一些關於基准測試的基本問題:是否選擇了正確的基准測試?是否為問題收集了相關的數據?是否采用了錯誤的測試標准? 接著,確認測試結果是否可重復。每次重新測試之前要確保系統狀態的一致,甚至有必要重啟系統並預熱,還需要確保預熱的時間足夠長,並可重復。如果預熱采用的隨機查詢,那麼測試結果可能就是不可重復的。 每次測試要保證測試數據相同,一個確保物理磁盤數據的分布盡可能一直的辦法是,每次都進行快速格式化並進行磁盤分區復制。 每次測試中,修改的參數應該盡量少,有時參數之間的依賴性會給測試帶來復雜性。一般情況下,都是通過迭代逐步地修改基准測試的參數,而避免每次運行都做大量的修改。
基於MySQL默認配置的測試沒有什麼意義。 如果測試中出現異常結果,不要輕易當作壞數據點而丟棄。分析這些異常結果,偶爾也會獲得意想不到的收獲。
2.3.5 運行基准測試並分析結果
通常來說,自動化基准測試可以獲得更精確的測試結果。要盡可能地使所有測試過程都自動化,包括裝載數據、系統預熱、執行測試、記錄結果等。 基准測試通常要運行多次,以提高測試結果的准確度。 獲得測試結果後,還需要對結果進行分析,最終目的是回答在設計測試時的問題。 如何從數據中抽象出有意義的結果,依賴於如何收集數據。通常使用腳本來分析數據,不僅減輕分析的工作量,也易於文檔化。
2.3.6 繪圖的重要性
在執行基准測試的時候盡可能地收集更多的細節數據,然後將數據繪制成圖形,這樣可以幫助快速地發現問題。
2.4 基准測試工具
2.4.1 集成式測試工具
ab:ab是一個Apache HTTP服務器基准測試工具。它可以測試HTTP服務器每秒最多可以處理多少請求。
http_load:這個工具概念上和ab類似,也被設計為對Web服務器進行測試,但比ab要更加靈活。可以通過一個輸入文件提供多個URL,http_load在這些URL中隨機選擇進行測試。
JMeter:JMeter是一個Java應用程序,可以加載其他應用並測試其性能。JMeter比ab和http_load都要復雜得多。
2.4.2 單組件式測試工具
mysqlslap:mysqlslap可以模擬服務器的負載,並輸出計時信息。測試時可以執行並發連接數,並指定SQL語句,如果沒有指定SQL語句,mysqlslap會自動生成查詢schema的SELECT語句。
MySQL Benchmark Suite(sql-bench):可以用於在不同數據庫服務器上進行比較測試。它是單線程的,主要用於測試服務器執行查詢的速度,結果會顯示哪種類型的操作在服務器上執行得更快。
Super Smack:Super Smack是一款用於MySQL和PostgreSQL的基准測試工具,可以提供壓力測試和負載生成。這是一個復雜而強大的工具,可以模擬多用戶訪問,可以加載測試數據到數據庫,並支持使用隨機數據填充測試表。
Database Test Suite:這是一款類似某些工業標准測試的測試工具集,其中的dbt2就是一款免費的TPC-C OLTP測試工具(未認證)。
Percona’s TPCC-MySQL Tool:一個類似TPC-C的基准測試工具集,其中有部分是專門為MySQL測試開發的。
sysbench:sysbench是一款多線程系統壓測工具,它可以根據影響數據庫服務器性能的各種因素來評估系統的性能。sysbench是一種全能測試工具,支持MySQL、操作系統和硬件的硬件測試。
2.5 基准測試案例(P52~P65)
2.6 總結
每個MySQL的使用者都應該了解一些基准測試的知識。 基准測試不僅僅是用來解決業務問題的一種時間行動,也是一種很好的學習方法。 如果你還沒有做過基准測試,那麼建議至少要熟悉sysbench。可以先學習如何使用OLTP和FILEIO測試。OLTP基准測試可以很方便地比較不同系統的性能。另一方面,文件系統和磁盤基准測試,則可以在系統出現問題時有效地診斷和隔離異常的組件。 如果經常執行基准測試,那麼指定一些原則是很有必要的。選擇一些合適的測試工具並深入地學習。可以建立一個腳本庫,用於配置基准測試,收集輸出結果、系統性能和狀態信息,以及分析結果。