MySQL學習 - 基準測試

xiaohan.liang?發表於2019-05-02

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 就可以了


相關文章