Sysbench 使用總結

Sysbench使用總結

實踐環境

CentOS 7.8mysql

Sysbench 1.0.20git

下載地址:https://github.com/akopytov/sysbench/archive/refs/tags/1.0.20.tar.gzgithub

用法介紹

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

具體說明:sql

  • testnameshell

    可選的內置測試類型名稱、或者是和工具捆綁的lua腳本名稱(不帶後綴.lua),形如oltp_read_only,或者是指定lua腳本的路徑,形如sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua ,可選內置測試名稱以下:數據庫

    fileio 文件I/O測試數組

    cpu CPU性能測試dom

    memory 內存測試函數

    threads POSIX線程性能測試工具

    mutex 執行Mutext性能測試(調度程序性能測試)

    說明:當testname指定爲lua腳本名稱時,實際執行時,會到sysbench_installation_home/share/sysbench目錄下查找對應名稱的腳本,找到後再執行腳本。

    可經過sysbench <testname> help查看每種測試支持的選項

    問題:若是testnamelua腳本名稱、lua腳本路徑時,咋知道該腳本支持的選項有哪些,選項參數默認值爲多少呢?

    解答:這個就要看testname對應腳本引用的common.lua腳本文件,該文件中定義的set_vars函數定義了命令支持的選項,以及對應的默認值,具體參見下文。而後,分析待執行的腳本中用到了哪些選項。

  • command 命令會被傳遞給內置測試名稱或者由testname指定的腳本,其定義了測試必須執行的動做。可用命令列表取決於特定的測試,有些測試也實現了本身的命令。如下爲典型的測試命令的描述:

    • prepare 測試前的準備操做,好比爲fileio測試建立必要的文件,或者爲數據庫測試基線填充測試數據庫。

    • run 運行由testname參數指定的測試。全部測試都支持該命令。

    • cleanup 測試運行完成後,移除測試建立的臨時數據,好比刪除建立的表

    • help 顯示testname使用幫助

  • options 可選項,常見選項許下

    經常使用通常命令行選項

    --threads 須要建立的worker線程數量 默認值 1

    --events=N 設置指望執行的事件總數。0表示不限制 默認值 0

    --time=N 設置總執行時間,單位秒。0表示不限制。 默認值 10

    --forced-shutdown=STRING 超過--time限制後,關閉程序以前須要等待的秒數,若是設置爲off則表示不啓用。 默認值 off

    --rate=N 平均事務速率。 0表示不限制。默認值 0
    --report-interval=N 設置按期報告中間統計的時間間隔爲N,單位爲秒 。 0表示不設置。默認值 0

    注意:

    1. 若是運行程序命令時,若是當前總執行時間已經達到--time選項參數值(默認10秒),無論當前已執行事件總數是否達到--events選項參數值,都會中止運行程序,因此若是須要爲程序命令顯示指定--events選項時,須要合理的設置--time選項參數值。
    2. 若是運行程序命令時,若是當前已執行事件總數已達到--events選項參數值,無論當前總執行時間是否達到--time選項參數值,都會中止測試

    經常使用日誌選項

    --verbosity=N 日誌詳細級別 {5 - debug, 0 - 僅critical messages} 默認值 3

    --percentile=N 延時統計(latency statistics)中,須要計算的百分比 (1-100)。設置爲0表示禁用百分比值計算。 Use the special

    經常使用數據庫選項

    --db-driver=STRING 設置程序使用的數據庫驅動。默認值 mysql

    經常使用mysql 選項:
    --mysql-host=host mysql服務主機地址 默認localhost
    --mysql-port=3306 mysql服務端口 默認值 3306
    --mysql-user=STRING mysql用戶名稱 默認值 sbtest
    --mysql-password=STRING mysql密碼,默認值 []
    --mysql-db=STRING mysql數據庫名稱 默認 sbtest

應用實踐

mysql數據庫性能基準測試

建立數據庫

CREATE DATABASE `sbtest` DEFAULT CHARACTER SET utf8;

注意:若是不事先建立數據庫,則運行一下測試腳本時,會報錯:FATAL: error 1049: Unknown database 'sbtest'

插入數據測試

運行壓測準備命令

# sysbench --oltp-tables-count=5 --oltp_table_size=0 --mysql-host=10.118.80.88 --mysql-user=testacc --mysql-password=test1234 sysbench-1.0.20/tests/include/oltp_legacy/insert.lua prepare

說明:

一、執行以上命令後,會自動建立5張空表

二、sysbench-1.0.20/tests/include/oltp_legacy/insert.luasysbench工具壓縮包中自帶腳本,下文所用到的腳本皆非自定義腳本,再也不贅述

運行插入數據測試

# sysbench --threads=80 --time=600 --events=50000000 --oltp-tables-count=5 --oltp_table_size=10000000 --mysql-host=10.118.80.88 --mysql-user=testacc --mysql-password=test1234 sysbench-1.0.20/tests/include/oltp_legacy/insert.lua run > result.txt

查看運行結果

混合操做測試

# sysbench  --threads=300 --time=1200 --oltp-tables-count=5 --oltp_table_size=10000000 mysql-host=10.118.80.88 --mysql-user=testacc --mysql-password=test1234 sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua run > result.txt

運行清理命令

# sysbench --oltp-tables-count=5 --mysql-host=10.118.80.88 --mysql-user=testacc --mysql-password=test1234 sysbench-1.0.20/tests/include/oltp_legacy/insert.lua cleanup

注意:執行preparecleanup命令時的--oltp-tables-count選項參數值要保持一致

lua腳本分析

sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua

具體分析參見中文註釋

pathtest = string.match(test, "(.*/)") # 首先,正則匹配當前測試名稱(sysbench命令行提供的testname)

if pathtest then # 若是測試名稱正則匹配 .*/
   # 說明測試名稱爲腳本,形如sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua,由於測試腳本和common.lua位於同一層級目錄,因此,拼接腳本所在目錄路徑和"common.lua"獲得common.lua文件路徑,而後,加載文件
   dofile(pathtest .. "common.lua") 
else # 不然,加載工具捆綁的common腳本,即sysbench_installation_home/share/sysbench/common.lua
   require("common")
end


function thread_init() # 線程初始化函數定義
   set_vars() # 調用common中的set_vars函數設置變量

   # 若是數據庫驅動爲mysql、attachsql,而且mysql表引擎爲myisam 
   if (((db_driver == "mysql") or (db_driver == "attachsql")) and mysql_table_engine == "myisam") then
      # 則走下述邏輯
      local i
      local tables = {}
      # 根據命令行oltp_tables_count參數值,初始化tables數組元素爲表名,格式形如sbtestN WRITE,其中N從1開始,最大值等於oltp_tables_count,即表數量
      for i=1, oltp_tables_count do 
         tables[i] = string.format("sbtest%i WRITE", i)
      end
      begin_query = "LOCK TABLES " .. table.concat(tables, " ,")
      commit_query = "UNLOCK TABLES"
   else # 不然定義事務起始查詢語句爲 begin_query爲BEGIN,結束查詢語句爲 COMMIT
      begin_query = "BEGIN"
      commit_query = "COMMIT"
   end

end

# 定義函數 用於獲取查詢條件
function get_range_str()
   local start = sb_rand(1, oltp_table_size) # 隨機獲取 [1, 單表記錄總數] 範圍內的整數,做爲範圍查詢條件起始值
   return string.format(" WHERE id BETWEEN %u AND %u",
                        start, start + oltp_range_size - 1) # 返回查詢條件WHERE id BETWEEN start AND (start + 99) (oltp_range_size默認爲100
end

定義待執行的「事件」函數
function event()
   local rs # 查詢返回結果
   local i   
   local table_name
   # 如下變量用於存放字段值和查詢
   local c_val
   local pad_val
   local query

   table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) # 隨機獲取表名,格式形如 sbtestN,其中N爲從[1,表數量]範圍內的隨機整數
   if not oltp_skip_trx then # 若是不跳過事務,
      db_query(begin_query) # 則執行do_query(oltp_skip_trx默認爲false,因此這裏會執行do_query),即標記事務開始
   end
   
    
   if not oltp_write_only then # 若是not oltp_write_only爲真(oltp_write_only默認爲false)
   # 則執行如下for循環(oltp_point_selects默認爲10次,因此,會執行10次for循環查詢,查詢語句爲:
   # SELECT c FROM table_name WHERE id=id_value
   # 說明:
   #  table_name   上述獲取的隨機表名,下同,再也不贅述
   #  c            非索引列
   #  id           主鍵列
   #  id_value     目標id值,隨機獲取已存在記錄ID
   for i=1, oltp_point_selects do
      rs = db_query("SELECT c FROM ".. table_name .." WHERE id=" ..
                       sb_rand(1, oltp_table_size))
   end

   if oltp_range_selects then # 若是oltp_range_selects爲true,(oltp_range_selects默認爲true)
   # 執行按範圍簡單查詢 1次(oltp_simple_ranges默認爲1次,因此只會執行1次for循環查詢)
   # SQL語句爲:
   # SELECT c FROM table_name WHERE id BETWEEN id_value1 AND id_value2 
   # 說明:
   #  id_value1   隨機獲取已存在記錄ID,下同,再也不贅述
   #  id_value2   id_value1 + 99,下同,再也不贅述
   for i=1, oltp_simple_ranges do 
      rs = db_query("SELECT c FROM ".. table_name .. get_range_str())
   end


   # 執行 按範圍sum查詢  1次 (oltp_sum_ranges默認值爲 1,因此只會執行1次for循環查詢)
   # SQL語句爲:
   # SELECT sum(c) FROM table_name WHERE id BETWEEN id_value1 AND id_value2 
   for i=1, oltp_sum_ranges do 
      rs = db_query("SELECT SUM(K) FROM ".. table_name .. get_range_str())
   end

   # 執行 按範圍排序查詢  1次 (oltp_order_ranges默認值爲 1,因此只會執行1次for循環查詢)
   # SQL語句爲:
   # SELECT c FROM table_name WHERE id BETWEEN id_value1 AND id_value2 ORDER BY c
   for i=1, oltp_order_ranges do
      rs = db_query("SELECT c FROM ".. table_name .. get_range_str() ..
                    " ORDER BY c")
   end

   # 執行 DISTINCT 排序查詢 1次 (oltp_distinct_ranges默認值爲 1,因此只會執行1次for循環查詢)
   # SQL語句爲:
   # SELECT DISTINCT c FROM table_name WHERE id BETWEEN id_value1 AND id_value2 ORDER BY c
   for i=1, oltp_distinct_ranges do
      rs = db_query("SELECT DISTINCT c FROM ".. table_name .. get_range_str() ..
                    " ORDER BY c")
   end

   end

   end
   
   if not oltp_read_only then # not oltp_read_only爲真(oltp_read_only默認爲false)
   # 執行 更新索引列字段操做 1次 (oltp_index_updates默認值爲 1,因此只會執行1次for循環查詢)
   # SQL語句爲:
   # UPDATE table_name SET k=k+1  WHERE id=id_value
   # 說明:
   #   k爲索引列字段
   for i=1, oltp_index_updates do
      rs = db_query("UPDATE " .. table_name .. " SET k=k+1 WHERE id=" .. sb_rand(1, oltp_table_size))
   end

   # 執行 更新非索引列字段操做 1次 (oltp_index_updates默認值爲 1,因此只會執行1次for循環查詢)
   # SQL語句爲:
   # UPDATE table_name SET c="c_val"  WHERE id=id_value
   # 說明:
   #  c_val  長度爲119位字符的隨機字符串
   for i=1, oltp_non_index_updates do
      c_val = sb_rand_str("###########-###########-###########-###########-###########-###########-###########-###########-###########-###########") # 長度爲119位字符的隨機字符串
      query = "UPDATE " .. table_name .. " SET c='" .. c_val .. "' WHERE id=" .. sb_rand(1, oltp_table_size)
      rs = db_query(query)
      if rs then
        print(query) # 打印查詢結果
      end
   end
   
   # 執行 刪除指定記錄操做 1次 (oltp_delete_inserts默認值爲 1,因此只會執行1次for循環查詢)
   # SQL語句爲:
   # DELETE FROM table_name WHERE id=id_value1
   for i=1, oltp_delete_inserts do

   i = sb_rand(1, oltp_table_size)

   rs = db_query("DELETE FROM " .. table_name .. " WHERE id=" .. i)
   
   c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]]) 
   pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]]) # 64位隨機字符串 
   
   # 執行 插入數據操做 1次
   # SQL語句爲:
   # INSERT INTO table_name(id, K, c, pad)VALUES(id_value, num, field_value1, field_value2 )
   # 說明:
   #   num   [1,表記錄數] 範圍內的隨機整數
   #   field_value1  119位隨機字符串 
   #   field_value2  64位隨機字符串 
    rs = db_query("INSERT INTO " .. table_name ..  " (id, k, c, pad) VALUES " .. string.format("(%d, %d, '%s', '%s')",i, sb_rand(1, oltp_table_size) , c_val, pad_val))

   end

   end -- oltp_read_only

   if not oltp_skip_trx then
      db_query(commit_query)
   end

end
sysbench-1.0.20/tests/include/oltp_legacy/common.lua

具體分析參見中文註釋

-- Input parameters
-- oltp-tables-count - number of tables to create
-- oltp-secondary - use secondary key instead PRIMARY key for id column
--
--

# 定義插入函數
function create_insert(table_id)

   local index_name
   local i
   local j
   local query

   if (oltp_secondary) then
     index_name = "KEY xid"
   else
     index_name = "PRIMARY KEY"
   end

   if (pgsql_variant == 'redshift') then
      auto_inc_type = "INTEGER IDENTITY(1,1)"
   else
      auto_inc_type = "SERIAL"
   end

   i = table_id

   print("Creating table 'sbtest" .. i .. "'...")
   # 根據不一樣驅動,執行對應建表語句,表名格式 sbtestN,其中N從1開始,最大值爲oltp_tables_count
   if ((db_driver == "mysql") or (db_driver == "attachsql")) then
      query = [[
CREATE TABLE sbtest]] .. i .. [[ (
id INTEGER UNSIGNED NOT NULL ]] ..
((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[,
k INTEGER UNSIGNED DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) /*! ENGINE = ]] .. mysql_table_engine ..
" MAX_ROWS = " .. myisam_max_rows .. " */ " ..
   (mysql_table_options or "")

   elseif (db_driver == "pgsql") then
      query = [[
CREATE TABLE sbtest]] .. i .. [[ (
id ]] .. auto_inc_type .. [[ NOT NULL,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) ]]

   elseif (db_driver == "drizzle") then
      query = [[
CREATE TABLE sbtest (
id INTEGER NOT NULL ]] .. ((oltp_auto_inc and "AUTO_INCREMENT") or "") .. [[,
k INTEGER DEFAULT '0' NOT NULL,
c CHAR(120) DEFAULT '' NOT NULL,
pad CHAR(60) DEFAULT '' NOT NULL,
]] .. index_name .. [[ (id)
) ]]
   else
      print("Unknown database driver: " .. db_driver)
      return 1
   end

   db_query(query)

   print("Inserting " .. oltp_table_size .. " records into 'sbtest" .. i .. "'")

   if (oltp_auto_inc) then
      db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(k, c, pad) VALUES")
   else
      db_bulk_insert_init("INSERT INTO sbtest" .. i .. "(id, k, c, pad) VALUES")
   end

   local c_val
   local pad_val


   # for循環,往表插入數據,直到插入oltp_table_size條記錄
   for j = 1,oltp_table_size do

   c_val = sb_rand_str([[
###########-###########-###########-###########-###########-###########-###########-###########-###########-###########]])
   pad_val = sb_rand_str([[
###########-###########-###########-###########-###########]])

      if (oltp_auto_inc) then
	 db_bulk_insert_next("(" .. sb_rand(1, oltp_table_size) .. ", '".. c_val .."', '" .. pad_val .. "')")
      else
	 db_bulk_insert_next("("..j.."," .. sb_rand(1, oltp_table_size) .. ",'".. c_val .."', '" .. pad_val .. "'  )")
      end
   end

   db_bulk_insert_done()

   if oltp_create_secondary then
     print("Creating secondary indexes on 'sbtest" .. i .. "'...")
     db_query("CREATE INDEX k_" .. i .. " on sbtest" .. i .. "(k)")
   end

end

# 定義執行prepare命令時調用的函數
function prepare()
   local query
   local i
   local j

   set_vars() # 設置變量

   db_connect() # 鏈接數據庫


   # for循環插入數據,循環次數爲 oltp_tables_count,
   for i = 1,oltp_tables_count do
     create_insert(i) 
   end

   return 0
end

# 定義執行clean命令時調用的函數
function cleanup()
   local i

   set_vars() # 調用set_vars函數,設置變量

   for i = 1,oltp_tables_count do
   print("Dropping table 'sbtest" .. i .. "'...") 
   db_query("DROP TABLE IF EXISTS sbtest".. i ) # 刪除表sbtestN,其中N從1~ oltp_tables_count,即表數量
   end
end

function set_vars()
   # 如下非本地變量的默認值都爲 nil
   oltp_table_size = tonumber(oltp_table_size) or 10000  # 單表記錄總數 默認值10000
   oltp_range_size = tonumber(oltp_range_size) or 100    # between and 範圍查詢 默認值100
   oltp_tables_count = tonumber(oltp_tables_count) or 1    # 表數量 默認值 1
   oltp_point_selects = tonumber(oltp_point_selects) or 10 # 按點查詢次數(where id=) 默認值 10
   oltp_simple_ranges = tonumber(oltp_simple_ranges) or 1  # 簡單查詢次數 默認值 1
   oltp_sum_ranges = tonumber(oltp_sum_ranges) or 1      # sum查詢次數 默認值 1
   oltp_order_ranges = tonumber(oltp_order_ranges) or 1  # order by排序查詢次數 默認值 1
   oltp_distinct_ranges = tonumber(oltp_distinct_ranges) or 1 # distinct範圍查詢次數 默認值 1
   oltp_index_updates = tonumber(oltp_index_updates) or 1     # 更新索引列操做次數 默認值 1
   oltp_non_index_updates = tonumber(oltp_non_index_updates) or 1 # 更新索引列字段操做次數 默認值 1
   oltp_delete_inserts = tonumber(oltp_delete_inserts) or 1   # 執行刪除記錄操做次數 默認值 1

   if (oltp_range_selects == 'off') then
      oltp_range_selects = false
   else 
      oltp_range_selects = true
   end

   if (oltp_auto_inc == 'off') then
      oltp_auto_inc = false
   else
      oltp_auto_inc = true
   end

   if (oltp_read_only == 'on') then
      oltp_read_only = true
   else
      oltp_read_only = false
   end

   if (oltp_write_only == 'on') then
      oltp_write_only = true
   else
      oltp_write_only = false
   end

   if (oltp_read_only and oltp_write_only) then
      error("--oltp-read-only and --oltp-write-only are mutually exclusive")
   end

   if (oltp_skip_trx == 'on') then
      oltp_skip_trx = true
   else
      oltp_skip_trx = false
   end

   if (oltp_create_secondary == 'off') then
      oltp_create_secondary = false
   else
      oltp_create_secondary = true
   end

   if (pgsql_variant == 'redshift') then
      oltp_create_secondary = false
      oltp_delete_inserts = 0
   end

end

運行結果說明

混合操做壓測結果爲例

# cat result.txt
sysbench 1.0.20 (using bundled LuaJIT 2.1.0-beta2)

Running the test with following options:
Number of threads: 300
Initializing random number generator from current time


Initializing worker threads...

Threads started!

SQL statistics:
    queries performed:
        read:                            34507228
        write:                           9859208
        other:                           4929604
        total:                           49296040
    transactions:                        2464802 (2053.74 per sec.)
    queries:                             49296040 (41074.74 per sec.)
    ignored errors:                      0      (0.00 per sec.)
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          1200.1525s
    total number of events:              2464802

Latency (ms):
         min:                                  129.86
         avg:                                  146.06
         max:                                  806.70
         95th percentile:                      155.80
         sum:                            360014005.42

Threads fairness:
    events (avg/stddev):           8216.0067/329.90
    execution time (avg/stddev):   1200.0467/0.04

結果項說明:

SQL statistics:
    queries performed:                   執行的SQL查詢:
        read:                            讀請求次數
        write:                           寫請求次數
        other:                           其它請求次數
        total:                           總請求次數
    transactions:                        執行的事務總數   (每秒事務數.)
    queries:                             執行的查詢總次數   (每秒查詢次數.)
    ignored errors:                      忽略錯誤數      (每秒忽略錯誤次數.)
    reconnects:                          數據庫重連次數      (每秒重連次數.)

General statistics:
    total time:                          總運行時間,以秒爲單位
    total number of events:              總執行事件數

Latency (毫秒爲單位):
         min:                                  最小請求響應時間
         avg:                                  平均請求響應時間
         max:                                  最大請求響應時間
         95th percentile:                      95%的請求響應時間
         sum:                                  總請求響應時間

Threads fairness:
    events (avg/stddev):           執行的事件總數(平均每一個線程執行的事件總數/標準差)
    execution time (avg/stddev):   執行耗時(平均每一個線程執行事件耗時/標準差)

參考鏈接

https://github.com/akopytov/sysbench#general-command-line-options

相關文章
相關標籤/搜索