什么是基準(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前端)
-
能夠測試整個系統(tǒng)的性能,包括web服務(wù)器緩存、數(shù)據(jù)庫等;能反映出系統(tǒng)中各個組件接口之間的性能問題,體現(xiàn)真實性能狀況
-
測試用例設(shè)計復(fù)雜,消耗時間長
-
- 2、單獨對MySQL進(jìn)行基準(zhǔn)測試:僅測試系統(tǒng)中的MySQL服務(wù)
-
測試用例設(shè)計簡單,所需耗時少
-
無法全面了解整個系統(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)確
-
使用數(shù)據(jù)庫的全量備份數(shù)據(jù)來進(jìn)行測試
-
- 在多用戶場景中,只做了單用戶的測試
-
使用多線程并發(fā)測試
-
- 在單服務(wù)器上測試分布式應(yīng)用
-
應(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ù)時,不會運行測試腳本,而是把生成的腳本打印出來 |
- 更多參數(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