關(guān)于MySQL的基準(zhǔn)測試

什么是基準(zhǔn)測試

當(dāng)我們對數(shù)據(jù)庫進(jìn)行優(yōu)化后,只有進(jìn)行測量系統(tǒng)性能才能知道優(yōu)化是否有效,這種測量的方式就是基準(zhǔn)測試?;鶞?zhǔn)測試的定義如下:

基準(zhǔn)測試是一種測量和評估軟件性能指標(biāo)的活動用于建立某個時刻的性能基準(zhǔn),以便當(dāng)系統(tǒng)發(fā)生軟/硬件變化時,重新進(jìn)行基準(zhǔn)測試以評估變化對性能的影響

我們可以這樣認(rèn)為:

基準(zhǔn)測試是針對系統(tǒng)設(shè)置的一種壓力測試,可以用來觀察系統(tǒng)在不同壓力下的行為。評估系統(tǒng)的容量,觀察系統(tǒng)如何處理不同的數(shù)據(jù)。

但是基于測試不等同于壓力測試:

  • 基于測試:直接、簡單、易于比較,用于評估服務(wù)器的處理能力?;鶞?zhǔn)測試可能不關(guān)心業(yè)務(wù)邏輯,所使用的查詢和業(yè)務(wù)的真實性可以和業(yè)務(wù)環(huán)節(jié)沒有關(guān)系
  • 壓力測試:對真實的業(yè)務(wù)數(shù)據(jù)進(jìn)行測試,獲得真實系統(tǒng)所能承受的壓力。壓力測試需要針對不同的主題,所使用的數(shù)據(jù)和查詢也是真實用到的

對MySQL進(jìn)行基準(zhǔn)測試的目的:

  • 1、建立MySQL服務(wù)器的性能基準(zhǔn)線,確定當(dāng)前MySQL服務(wù)器的運行情況
  • 2、模擬比當(dāng)前系統(tǒng)更高的負(fù)載,以找出系統(tǒng)的擴(kuò)展瓶頸。增加數(shù)據(jù)庫的并發(fā),觀察QPS、TPS的變化,以確定并發(fā)量與性能最優(yōu)的關(guān)系
  • 3、測試不同的硬件、軟件和操作系統(tǒng)配置
  • 4、證明新的硬件設(shè)備是否配置正確

如何進(jìn)行基準(zhǔn)測試

通常來說,基準(zhǔn)測試有兩種方式:

  • 1、對整個系統(tǒng)進(jìn)行基準(zhǔn)測試:從系統(tǒng)的入口進(jìn)行測試(網(wǎng)站W(wǎng)eb前端,手機(jī)APP前端)
    • \color{#CC394A}{優(yōu)點:}能夠測試整個系統(tǒng)的性能,包括web服務(wù)器緩存、數(shù)據(jù)庫等;能反映出系統(tǒng)中各個組件接口之間的性能問題,體現(xiàn)真實性能狀況
    • \color{#CC394A}{缺點:}測試用例設(shè)計復(fù)雜,消耗時間長
  • 2、單獨對MySQL進(jìn)行基準(zhǔn)測試:僅測試系統(tǒng)中的MySQL服務(wù)
    • \color{#CC394A}{優(yōu)點:}測試用例設(shè)計簡單,所需耗時少
    • \color{#CC394A}{缺點:}無法全面了解整個系統(tǒng)的性能基線

MySQL基準(zhǔn)測試的常見指標(biāo):

  • 單位時間內(nèi)所處理的事務(wù)數(shù)(TPS)
  • 單位時間內(nèi)所處理的查詢數(shù)(QPS)
  • 并發(fā)數(shù)量:同時處理的查詢請求數(shù)量
  • 單個測試任務(wù)的響應(yīng)時間
    • 包含:平均響應(yīng)時間、最小響應(yīng)時間、最大響應(yīng)時間及各時間所占百分比

基準(zhǔn)測試中容易忽略的問題:

  • 使用生產(chǎn)環(huán)境數(shù)據(jù)進(jìn)行測試時,只使用了部分?jǐn)?shù)據(jù),可能會導(dǎo)致測試結(jié)果不準(zhǔn)確
    • \color{#FF8C00}{推薦:}使用數(shù)據(jù)庫的全量備份數(shù)據(jù)來進(jìn)行測試
  • 在多用戶場景中,只做了單用戶的測試
    • \color{#FF8C00}{推薦:}使用多線程并發(fā)測試
  • 在單服務(wù)器上測試分布式應(yīng)用
    • \color{#FF8C00}{推薦:}應(yīng)使用相同的架構(gòu)進(jìn)行測試
  • 反復(fù)執(zhí)行同一查詢,問題在于同樣的SQL語句容易緩存命中,無法反應(yīng)真實查詢性能。而在實際的環(huán)境中查詢方式可能是不盡相同的

基準(zhǔn)測試的步驟:

  • 1、選擇是對整個系統(tǒng)還是某一個組件進(jìn)行測試,還需要確定使用什么樣的數(shù)據(jù)進(jìn)行測試
  • 2、準(zhǔn)備測試數(shù)據(jù)的收集腳本,通常需要盡可能多的收集當(dāng)前系統(tǒng)的信息,例如CPU使用率、IO、網(wǎng)絡(luò)流量、狀態(tài)與計數(shù)器信息等
  • 3、編寫腳本分析第二步所收集的基準(zhǔn)測試信息,最后得出測試結(jié)果

收集腳本和分析腳本示例

基準(zhǔn)測試數(shù)據(jù)的收集腳本:

#!/bin/bash
# 腳本的運行間隔
INTERVAL=5
# 創(chuàng)建數(shù)據(jù)文件的存儲目錄
STORE_DIR=/home/mysql/benchmarks
mkdir -p $STORE_DIR
# 將收集的數(shù)據(jù)存儲到哪個目錄下,以及文件前綴
PREFIX=$STORE_DIR/$INTERVAL-sec-status
# 設(shè)置腳本的運行標(biāo)識
RUNFILE=$STORE_DIR/running
touch $RUNFILE && echo "1" > $RUNFILE
# mysql的用戶名和密碼
USER=root
PWD=123456
# mysql命令所在的路徑
MYSQL="/usr/local/mysql/bin/mysql -u$USER -p$PWD"
# 記錄當(dāng)前mysql的全局變量
$MYSQL -e "show global variables" >> mysql-variables

# 運行標(biāo)識文件存在就會一直循環(huán)
while test -e $RUNFILE; do
    # 定義腳本運行時的當(dāng)前時間
    file=$(date +%F_%I)
    # 實現(xiàn)間隔運行該循環(huán)
    sleep=$(date +%s.%N | awk '{print 5 - ($1 % 5)}')
    sleep $sleep
    
    ts="$(date +"TS %s.%N %F %T")"
    # 獲取系統(tǒng)負(fù)載信息
    loadavg="$(uptime)"
    # 記錄系統(tǒng)負(fù)載信息
    echo "$ts $loadavg" >> $PREFIX-${file}-status
    # 記錄當(dāng)前mysql的全局變量信息
    $MYSQL -e "show global status" >> $PREFIX-${file}-status &
    echo "$ts $loadavg" >> $PREFIX-${file}-innodbstatus
    # 記錄當(dāng)前 innodb 的狀態(tài)信息
    $MYSQL -e "show engine innodb status" >> $PREFIX-${file}-innodbstatus &
    echo "$ts $loadavg" >> $PREFIX-${file}-processlist
    # 記錄當(dāng)前mysql全部連接信息列表
    $MYSQL -e "show full processlist\G" >> $PREFIX-${file}-processlist &
    echo $ts
done

echo Exiting because $RUNFILE does not exists

測試數(shù)據(jù)分析腳本:

#!/bin/bash
awk '
   BEGIN {
     printf "#ts date time load QPS";
     fmt=" %.2f";
   }
   /^TS/ {
   ts = substr($2,1,index($2,".")-1);
   load = NF -2;
   diff = ts - prev_ts;
   printf "\n%s %s %s %s",ts,$3,$4,substr($load,1,length($load)-1);
   prev_ts=ts;
   }
   /Queries/{
   printf fmt,($2-Queries)/diff;
   Queries=$2
   }
   ' "$@"

### 使用示例 ###
# sh ./analyze.sh ${測試數(shù)據(jù)文件路徑}
# 如:sh ./analyze.sh /home/mysql/benchmarks/5-sec-status-2020-01-11_04-status

Mysql基準(zhǔn)測試工具之mysqlslap

一般來說,我們都不會自己去編寫基準(zhǔn)測試的腳本,因為都有現(xiàn)成的工具。例如,mysql 5.1以上版本都自帶了mysqlslap這個基準(zhǔn)測試工具。由于是自帶的也無需進(jìn)行單獨的安裝,該工具位于mysql的bin目錄下。

功能簡介:

  • 模擬服務(wù)器負(fù)載,并輸出相關(guān)統(tǒng)計信息
  • 可以指定測試的查詢語句,也可以使用該工具自動生成的測試語句

常用參數(shù)說明:

參數(shù) 說明
--concurrency 并發(fā)數(shù)量,即模擬的客戶端數(shù)量,可以指定多個,使用逗號分隔
--iterations 指定測試的運行次數(shù)
--auto-generate-sql 使用系統(tǒng)自動生成的SQL腳本來進(jìn)行測試
--auto-generate-sql-add-autoincrement 在自動生成的表中增加自增ID
--auto-generate-sql-load-type 指定測試中使用的查詢類型(取值:read, write, update, mixed),默認(rèn)mixed
--auto-generate-sql-write-number 指定初始化數(shù)據(jù)時所生成的數(shù)據(jù)量
--engine 要測試表的存儲引擎,允許指定多個,使用逗號分隔
--no-drop 指定不清理測試數(shù)據(jù)
--number-of-queries 指定每一個連接執(zhí)行的查詢次數(shù)
--debug-info 指定輸出額外的內(nèi)存及CPU統(tǒng)計信息
--number-char-cols 指定測試表中包含的int類型的數(shù)量
--number-int-cols 指定測試表中包含的varchar類型的數(shù)量
--create-schema 指定用于執(zhí)行測試的數(shù)據(jù)庫的名稱
--query 用于指定自定義的SQL腳本
--only-print 指定該參數(shù)時,不會運行測試腳本,而是把生成的腳本打印出來

使用示例:

[root@localhost ~]# mysqlslap -uroot -p123456 --concurrency=1,50,100,200 --iterations=3 --number-int-cols=5 --number-char-cols=5 --auto-generate-sql --auto-generate-sql-add-autoincrement --engine=myisam,innodb --number-of-queries=10 --create-schema=test

運行該測試后,截取的部分輸出片段如下:

Benchmark
    # 運行的是myisam引擎的測試
    Running for engine myisam
    # 運行所有查詢的平均秒數(shù)
    Average number of seconds to run all queries: 0.020 seconds
    # 運行所有查詢的最小秒數(shù)
    Minimum number of seconds to run all queries: 0.018 seconds
    # 運行所有查詢的最大秒數(shù)
    Maximum number of seconds to run all queries: 0.022 seconds
    # 運行查詢的客戶端數(shù)
    Number of clients running queries: 1
    # 每個客戶端的平均查詢數(shù) 
    Average number of queries per client: 10

Benchmark
    Running for engine innodb
    Average number of seconds to run all queries: 0.049 seconds
    Minimum number of seconds to run all queries: 0.042 seconds
    Maximum number of seconds to run all queries: 0.059 seconds
    Number of clients running queries: 1
    Average number of queries per client: 10

Mysql基準(zhǔn)測試工具之sysbench

除了 mysqlslap 這個mysql自帶的基準(zhǔn)測試工具之外,還有一個常用的工具就是 sysbench。sysbench的功能比mysqlslap更多一些,能測試的點也更全面一些。sysbench除了可以測試MySQL外,還能測試系統(tǒng)的CPU、IO、內(nèi)存等方面。

安裝sysbench

sysbench的GitHub倉庫地址及源碼安裝文檔如下:

一般系統(tǒng)中不會自帶sysbench工具,需要我們自行安裝,我這里采用源碼編譯安裝的方式進(jìn)行安裝。首先到如下地址復(fù)制源碼包的下載鏈接:

然后到Linux上使用wget命令進(jìn)行下載:

[root@txy-server ~]# cd /usr/local/src
[root@txy-server /usr/local/src]# wget https://github.com/akopytov/sysbench/archive/1.0.19.tar.gz

安裝編譯sysbench時所依賴的一些庫:

[root@txy-server /usr/local/src]# yum -y install make automake libtool pkgconfig libaio-devel mariadb-devel openssl-devel

接著將下載好的源碼包進(jìn)行解壓縮,并進(jìn)入到解壓后的目錄:

[root@txy-server /usr/local/src]# tar -zxvf 1.0.19.tar.gz
[root@txy-server /usr/local/src]# cd sysbench-1.0.19/

最后參考以下步驟完成編譯安裝:

[root@txy-server /usr/local/src/sysbench-1.0.19]# ./autogen.sh
[root@txy-server /usr/local/src/sysbench-1.0.19]# ./configure --with-mysql-includes=/usr/local/mysql/include --with-mysql-libs=/usr/local/mysql/lib
[root@txy-server /usr/local/src/sysbench-1.0.19]# make && make install

等待完成編譯安裝后,測試是否安裝成功。我這里報了個找不到庫文件的錯誤:

[root@txy-server /usr/local/src/sysbench-1.0.19]# sysbench --version
sysbench: error while loading shared libraries: libmysqlclient.so.21: cannot open shared object file: No such file or directory

解決方式是建立一個該文件的軟連接到/usr/lib64/目錄下:

[root@txy-server /usr/local/src/sysbench-1.0.19]# ln -s /usr/local/mysql/lib/libmysqlclient.so.21  /usr/lib64/

再次測試,執(zhí)行成功:

[root@txy-server /usr/local/src/sysbench-1.0.19]# sysbench --version
sysbench 1.0.19

sysbench的使用

sysbench的命令格式如下:

sysbench [options]... [testname] [command] 

1、options,是指定測試參數(shù),以下是使用sysbench測試MySQL時常用的參數(shù):

  • --mysql-db:用于指定基準(zhǔn)測試的數(shù)據(jù)庫名稱,該數(shù)據(jù)庫必須是已存在的
  • --mysql_storage_engine:指定測試的MySQL存儲引擎
  • --tables:執(zhí)行測試的表的數(shù)量
  • --table_size:指定每個表中的數(shù)據(jù)量
  • --threads:指定測試的并發(fā)線程數(shù)量
  • --max-time:指定最大測試時間,單位為秒
  • --report-interval:指定間隔多長時間就輸出一次統(tǒng)計信息,單位為秒
  • --mysql-socket:指定mysql的.sock文件路徑,用于連接mysql
  • --mysql-user:指定用于測試時連接mysql的用戶
  • --mysql-password:指定mysql用戶的密碼
  • 關(guān)于其他參數(shù)詳見官方文檔

2、testname,是指定內(nèi)置的測試類型或測試腳本。內(nèi)置的測試類型有如下取值:

  • fileio:測試文件系統(tǒng)I/O性能
  • cpu:測試cpu性能
  • memory:測試內(nèi)存性能
  • threads:測試線程性能
  • mutex:測試互斥鎖性能
  • 執(zhí)行sysbench [testname] help,可以查看各個測試類型所支持的參數(shù)

除內(nèi)置測試類型以外的測試,就需要指定測試腳本。sysbench的測試腳本需要使用lua語言編寫,可以根據(jù)實際需求編寫自已的測試腳本,也可以使用sysbench自帶的測試腳本。sysbench自帶的lua腳本如下:

[root@txy-server ~]# ls /usr/local/share/sysbench
bulk_insert.lua  # 用于測試大量的insert操作性能
oltp_common.lua  # 公共文件,給其他腳本引用的,不可直接使用
oltp_delete.lua  # 用于測試oltp下的delete操作性能
oltp_insert.lua  # 用于測試oltp下的insert操作性能
oltp_point_select.lua   # 用于測試oltp下的定點查詢性能,例如根據(jù)主鍵查詢
oltp_read_only.lua   # 用于測試oltp下的只讀性能
oltp_read_write.lua  # 用于測試oltp下的讀寫性能
oltp_update_index.lua  # 用于測試更新索引字段的性能
oltp_update_non_index.lua  # 用于測試更新無索引字段操作的性能
oltp_write_only.lua  # 用于測試oltp下的寫操作性能
select_random_points.lua  # 用于測試隨機(jī)定點查詢的性能
select_random_ranges.lua  # 用于測試隨機(jī)范圍讀取的性能
...
  • Tips:不同版本的sysbench存放測試腳本的路徑可能不太一樣,需要自行確認(rèn)

3、command,則是指定一些測試操作,例如運行測試、清除數(shù)據(jù)或準(zhǔn)備數(shù)據(jù)等:

  • prepare:用于測試開始前準(zhǔn)備測試數(shù)據(jù)
  • run:用于測試數(shù)據(jù)準(zhǔn)備完成后,執(zhí)行測試
  • cleanup:用于測試執(zhí)行完成后清理測試數(shù)據(jù)

sysbench基準(zhǔn)測試示例

1、測試CPU性能

以下命令可以讓cpu找出10000以內(nèi)的素數(shù),并統(tǒng)計計算所需耗時,以此得知cpu的性能。需要注意的是,這種方式測試的是單核心性能,而非多核性能:

[root@txy-server ~]# sysbench --cpu-max-prime=10000 cpu run

測試結(jié)果如下:

# CPU速度
CPU speed:
    # 每秒事件數(shù)
    events per second:  1039.79

General statistics:
    # 計算出所有素數(shù)的總耗時
    total time:                          10.0005s  
    # 總的事件數(shù)
    total number of events:              10400

Latency (ms):
         # 計算出一個素數(shù)的最低耗時
         min:                                    0.94
         # 平均計算出一個素數(shù)的耗時
         avg:                                    0.96
         # 計算出一個素數(shù)的最長耗時
         max:                                    9.43
         # 95%情況是1.01毫秒計算出一個素數(shù)
         95th percentile:                        1.01
         # 合計耗時
         sum:                                 9994.05

# 線程公平性
Threads fairness:
    events (avg/stddev):           10400.0000/0.00
    execution time (avg/stddev):   9.9941/0.00

2、測試系統(tǒng)I/O性能

測試I/O性能需要先準(zhǔn)備測試數(shù)據(jù),測試數(shù)據(jù)的大小需要大于物理內(nèi)存。命令如下:

# 該命令會生成127個測試文件,這些文件合計4G大小
[root@txy-server ~]# sysbench --file-total-size=4G fileio prepare
...
Creating file test_file.125
Creating file test_file.126
Creating file test_file.127
4294967296 bytes written in 39.00 seconds (105.04 MiB/sec).
[root@txy-server ~]#

數(shù)據(jù)準(zhǔn)備好后,執(zhí)行測試:

[root@txy-server ~]# sysbench --threads=8 --file-total-size=4G --file-test-mode=rndrw --report-interval=1 fileio run

參數(shù)說明:

  • --threads=8:設(shè)置并發(fā)線程數(shù)為8
  • --file-test-mode=rndrw:指定文件測試模式為隨機(jī)讀寫,即測試磁盤I/O的隨機(jī)讀寫性能
  • --report-interval=1:指定每秒輸出一次統(tǒng)計信息

測試結(jié)果如下:

File operations:
    reads/s:                      2089.75
    writes/s:                     1392.67
    fsyncs/s:                     4553.64

Throughput:
    # 每秒讀取
    read, MiB/s:                  32.65
    # 
    written, MiB/s:               21.76

General statistics:
    total time:                          10.0778s
    total number of events:              79973

Latency (ms):
         min:                                    0.00
         avg:                                    1.00
         max:                                   58.42
         95th percentile:                        3.13
         sum:                                79895.62

Threads fairness:
    events (avg/stddev):           9996.6250/43.23
    execution time (avg/stddev):   9.9870/0.01

最后執(zhí)行cleanup操作,清除測試數(shù)據(jù):

[root@txy-server ~]# sysbench --file-total-size=4G fileio cleanup

3、測試MySQL性能

由于sysbench內(nèi)置的測試類型沒有MySQL,所以在使用sysbench測試MySQL時,testname需要指定為測試腳本的路徑。sysbench自帶了一些MySQL的測試腳本,所以無特殊需求的情況下,我們也無需自己去編寫測試腳本。接下來,進(jìn)行一個簡單的演示,看看如何使用測試腳本來測試MySQL的性能。

首先也是需要準(zhǔn)備數(shù)據(jù),命令如下:

[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua prepare
  • Tips:該腳本用于測試OLTP下的讀寫性能。另外,筆者這里為了方便就直接使用root賬戶,在實際測試中,務(wù)必創(chuàng)建一個用于測試的賬戶

執(zhí)行測試:

[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua run

測試結(jié)果如下:

SQL statistics:
    queries performed:
        # 讀取操作的總數(shù)
        read:                            10444
        # 寫操作的總數(shù)
        write:                           2984
        # 其他操作的總數(shù),例如commit等
        other:                           1492
        # 總共執(zhí)行的操作數(shù)量
        total:                           14920
    # 每秒執(zhí)行的事務(wù)數(shù),即TPS,這里為每秒74.48次
    transactions:                        746    (74.48 per sec.)
    # 每秒查詢的數(shù)量,即QPS,這里為每秒1489.53次
    queries:                             14920  (1489.53 per sec.)
    # 忽略的錯誤次數(shù)
    ignored errors:                      0      (0.00 per sec.)
    # 重連次數(shù)
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          10.0150s
    total number of events:              746

Latency (ms):
         min:                                    8.86
         avg:                                   13.42
         max:                                   99.97
         95th percentile:                       20.00
         sum:                                10009.79

Threads fairness:
    events (avg/stddev):           746.0000/0.00
    execution time (avg/stddev):   10.0098/0.00

同樣,最后需要清理測試數(shù)據(jù):

[root@txy-server ~]# sysbench --mysql_storage_engine=innodb --table_size=10000 --mysql-db=test --tables=10 --mysql-socket=/tmp/mysql.sock --mysql-user=root --mysql-password=123456 /usr/local/share/sysbench/oltp_read_write.lua cleanup

如果想要知道測試腳本具體支持哪些參數(shù),其查看方式和內(nèi)置測試類型是一樣的,只不過把測試類型的名稱換成了腳本而已:

[root@txy-server ~]# sysbench /usr/local/share/sysbench/oltp_read_write.lua help
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容