Python社区  »  DATABASE

MySQL学习 - 基准测试

xiaohan.liang🥚 • 1 月前 • 58 次点击  
阅读 31

MySQL学习 - 基准测试

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


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/32412
 
58 次点击  
分享到微博