zoukankan      html  css  js  c++  java
  • Sysbench 使用总结

    Sysbench使用总结

    实践环境

    CentOS 7.8

    Sysbench 1.0.20

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

    用法介绍

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

    具体说明:

    • testname

      可选的内置测试类型名称、或者是和工具捆绑的lua脚本名称(不带后缀.lua),形如oltp_read_only,或者是指定lua脚本的路径,形如sysbench-1.0.20/tests/include/oltp_legacy/oltp.lua ,可选内置测试名称如下:

      fileio 文件I/O测试

      cpu CPU性能测试

      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
    

    说明:

    1、执行以上命令后,会自动创建5张空表

    2、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

    作者:授客
    公众号:授客的知识库
    QQ:1033553122
    全国软件测试QQ交流群:7156436

    Git地址:https://gitee.com/ishouke
    友情提示:限于时间仓促,文中可能存在错误,欢迎指正、评论!
    作者五行缺钱,如果觉得文章对您有帮助,请扫描下边的二维码打赏作者,金额随意,您的支持将是我继续创作的源动力,打赏后如有任何疑问,请联系我!!!
                微信打赏                       支付宝打赏                        授课的知识库               全国软件测试交流QQ群  
                          

  • 相关阅读:
    word2013下,公式居中,编号右对齐
    Linux系统下,anaconda3与系统python共存
    LeetCode: 496 Next Greater Element I(easy)
    LeetCode: 463 Island Perimeter(easy)
    LeetCode: 620 Not Boring Movies(easy)
    C++: 其他类型转string
    LeetCode: 412 Fizz Buzz(easy)
    LeetCode: 344 Reverse String
    LeetCode: 566 Reshape the Matrix
    LeetCode: 575 Distribute Candies(easy)
  • 原文地址:https://www.cnblogs.com/shouke/p/14618738.html
Copyright © 2011-2022 走看看