MySQL學習 - 基準測試
1. Introduction
1.1 為什麼需要有基準測試
- 快速有效,瞭解系統在給定工作負荷下表現的方法
- 確認系統,是否按照預期工作
- 重現錯誤,輔助解決這些問題
- 模擬更高負載,提前預測效能瓶頸,規劃業務增長
1.2 基準測試 & 真實測試
- 基準測試 + 真實測試 : 只使用基準測試,case簡單很難反映出真實情況。只使用真實測試,情況複雜多變很難總結出確切結論
2. 設計基準測試的策略
2.1 我應該測試什麼 -> 全域性基準測試 & MySQL基準測試
- 什麼時候使用全域性基準測試
- 想要測試一整個應用,連同 Web伺服器+網路+資料庫 的整體表現
- 資料庫並不一定會是效能瓶頸,聯合全域性+資料測試驗證這個結論
- 什麼時候只針對MySQL展開基準測試
- 想要比較不同表,不同查詢語句間的效能差異
- 針對應用中某個具體問題的測試
2.2 選擇測試指標
你必須得抱有一定目的: "這個CPU相比與上一種是不是快一點?" "這個索引好用嗎?"
根據測試指標,分析,解答你一開始的疑惑
- 吞吐量: 單位時間事務處理數量, 一般用TPS作為單位
- 響應時間: 完成某個指定請求消耗的時間,取95%,最好將結果繪圖方便理解
- 併發性: 任意時間,同時發生的併發請求,你可以在Sysbench中指定,比如我要求現在併發64請求,然後測試這種環境下的響應速度等指標
- 原則 : 設計出你想了解的更多指標,指定可接受範圍
2.3 資料集從那兒來
- 最好的資料就是來自使用者真實使用的資料,你可以選擇記錄一下高峰時段下一小時的請求記錄,為了完全重現服務的狀態,使用多執行緒安排這些請求
- 如果沒有,或者真實記錄非常少,你需要模擬使用者的行為,但是作假也要做的像一點,比如不要均勻分佈請求,請求門類有熱點非熱點的區別
2.4 記錄下執行時的系統狀態
- 記錄下系統測試時的狀態 . 常見的系統指標包含 CPU使用率,磁碟IO,網路流量統計等資料記錄狀態的過程可以由Shell指令碼完成並儲存,最好是先記錄最原始的資料稍後在清洗等。
- 抵消影響因素 .
- 保證系統狀態一致: 理論上最好保持系統狀態一致,你甚至需要為此單獨重啟預熱系統
- 記憶體&資料碎片度: 為了保證記憶體的碎片度一致,可能需要每次快速格式化硬碟並分割槽
- 其他 :
- 修改基準測試引數: 為了達到最優效果,你可能會面臨引數調整的需求,一次修改儘可能少的引數,使用二分法,從而獲得最優引數
- MySQL的預設引數: MySQL的預設配置原則是儘量消耗少資源,為了獲得性能的最大化,你需要逐步挑選出最適合你業務的引數
- 如果出現了奇怪的資料,不要輕易丟棄: 嘗試分析/復現一下奇怪資料,會有一些新的發現,這可能是你程式碼上或者測試設計的有問題。沒有搞清楚前不要公佈測試結果
2.5 嘗試分析測試結果
- 嘗試使用gnuplot繪圖或者R繪圖的方式,結合記錄下的資料繪圖,髒資料不要丟嘗試分析
3. 基準測試工具
3.1 全域性測試工具
- ab : 基於單個URL展開的壓力測試
- http_load: 多個URL中隨機挑選的壓力測試
- JMeter: 更加複雜,甚至可以設定預熱時間,繪圖等
3.2 MySQL測試工具
- sysbench: 多執行緒壓測工具,它可以根據影響資料庫伺服器效能的各種因素,對系統性能評估,這些因素包含:檔案IO,作業系統排程器,記憶體分配等
4. 使用Sysbench測試計算機效能
4.1 sysbench <全域性引數> --test=<測試型別> <測試引數> <行動>
- 全域性引數
- num-threads 指定執行緒數量
- max-request 測試全過程最多發出多少請求
- max-time 超時設定
- report-interval 每隔多久列印一次測試概況
- mysql-host/port/socket/user/password/db
- 測試型別
- fileio / cpu / memory / threads / mutex / oltp / 指定指令碼
- 行動
- preprare 準備測試所需資料
- run 開始行動
- cleanup 清理測試資料
4.2 fileio 型測試
sysbench--test=fileio<測試型別 - fileio測試> --file-num=10<生成10個測試使用的檔案> --file-total-size=5G <所有檔案的一共5G> prepare<fileio測試 - 行動:準備檔案> sysbench--max-time=180<超時時間180秒> --max-requests=100000000<最多10000000請求> --num-threads=16<測試使用16執行緒> --init-rng=on<使用隨機數生成器> --test=fileio<測試型別 - fileio測試> --file-total-size=5G<所有檔案的一共5G> --file-test-mode=rndrw<測試型別 - 隨機寫> --file-num=10<生成10個測試使用的檔案> run<行動型別 - 執行測試> sysbench--test=fileio<測試型別 - fileio測試> --file-num=10<生成10個測試使用的檔案> --file-total-size=5G<所有檔案的一共5G> cleanup<行動型別 - 清除測試資料> 複製程式碼
4.3 CPU效能測試
sysbench --test=cpu --cpu-max-prime=20000 run <計算2萬以內最大素數>複製程式碼
假設現在針對兩臺電腦直接展開這樣的測試是不公平的,因為這裡執行緒數量被設定成1, 為了能表現出CPU的最大威力,我們應該如下設定執行緒數量
sysbench--test=cpu --num-threads=`grep "processor" /proc/cpuinfo | wc -l` <使用全部核心> --cpu-max-prime=20000 run複製程式碼
4.4 記憶體連續讀寫效能測試
sysbench--test=memory<測試記憶體> --memory-block-size=8K<測試記憶體塊大小為8k> --memory-total-size=1G<總共資料傳輸大小1G> --num-threads=16<執行緒數量16> run複製程式碼
5. 使用Sysbench 測試資料庫效能
5.1 測試例項
sysbench --mysql-host=127.0.0.1<指定資料庫相關引數> --mysql-port=3166 --mysql-user=root --mysql-password=123456 --test=oltp<測試型別為資料庫相關測試> --oltp_tables_count=1<生成一張表> --oltp-table-size=1000000<表裡有這些資料> --rand-init=on prepare<行動: 準備對應資料> sysbench --mysql-host=127.0.0.1 --mysql-port=3166 --mysql-user=root --mysql-password=123456 --test=tests/db/oltp.lua --oltp_tables_count=1 --oltp-table-size=1000000 --num-threads=128 --oltp-read-only=off --report-interval=10 --rand-type=uniform --max-time=60 --max-requests=10000000 run# 使用128執行緒測試60秒,每隔10秒傳送一次測試情況報告複製程式碼
5.2 Lua指令碼分析
local stmt_defs = { point_selects = { "SELECT c FROM sbtest%u WHERE id=?", t.INT}, simple_ranges = { "SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ?", t.INT, t.INT}, sum_ranges = { "SELECT SUM(k) FROM sbtest%u WHERE id BETWEEN ? AND ?", t.INT, t.INT}, order_ranges = { "SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c", t.INT, t.INT}, distinct_ranges = { "SELECT DISTINCT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c", t.INT, t.INT}, index_updates = { "UPDATE sbtest%u SET k=k+1 WHERE id=?", t.INT}, non_index_updates = { "UPDATE sbtest%u SET c=? WHERE id=?", {t.CHAR, 120}, t.INT}, deletes = { "DELETE FROM sbtest%u WHERE id=?", t.INT}, inserts = { "INSERT INTO sbtest%u (id, k, c, pad) VALUES (?, ?, ?, ?)", t.INT, t.INT, {t.CHAR, 120}, {t.CHAR, 60}}, }複製程式碼
上面是真的開始執行的時候,sysbench會去執行的命令
CREATE TABLE sbtest%d( id %s, k INTEGER DEFAULT '0' NOT NULL, c VARCHAR(500) DEFAULT '' NOT NULL, pad CHAR(60) DEFAULT '' NOT NULL, %s (id) ) %s %s]] 複製程式碼
CREATE TABLE sbtest%d( id %s, gmt_create datetime not null, gmt_modified datetime not null, k INTEGER DEFAULT '0' NOT NULL, c VARCHAR(500) DEFAULT '' NOT NULL, pad CHAR(60) DEFAULT '' NOT NULL, is_used INTEGER DEFAULT '0' NOT NULL, %s (id) ) %s %s]]複製程式碼
這個則是在prepare階段會去做的事,建立一張這樣的表,你也可以修改成你這樣,然後對應的修改 run的時候所要操作的指令,然後 prepare - run - cleanup 就可以了