社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

MySQL学习 - 基准测试

xiaohan.liang🥚 • 6 年前 • 210 次点击  
阅读 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
 
210 次点击