IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

使用sysbench来测试Row Cache解惑

淘宝JAVA中间件团队博客 2011-09-14 13:38:01 累计浏览 1,710 次
本机暂存

    最近大牛 姜承尧  也在测试Row Cache,发现使用sysbench来进行测试效果不是很明显.

    分析了一下 sysbench的三个测试场景uniform,gaussian,special都不是很符合Row Cache的使用场景导致效果不明显

    先来解释一下 Row Cache要解决的问题主要是在有热门数据且热门数据分布很离散的情况下Page缓存导致的内存利用率低的问题,我们做过测试,在innodb内部对Page访问打点的统计来看,一个row有500字节大小,热门数据大概占千分之一地情况下,Page缓存的利用率(就是16K读进来,真正被上层read的数据大小的比例)在20%以下,就是说 80%的内存是被浪费的.

    而现在MySQL的应用由于数据量巨大使用MySQL后都是分库分表,而且为了能每个库没有热点,基本都是按取模的方式进行分表,导致热门数据基本都是很平均的分布在各个不同的Page上.而分库分表之后基本没有了range查询,都是类似select * from test where uuid=XX这样的key-value类型的查询,这样的查询就导致了内存利用率低的问题

    Row Cache就是为了解决这样的场景(一般互联网应用规模到了一定程度应该都会有这个问题).

    接下来我们看看sysbench 3个场景的实现

  • uniform:
  • 1
    2
    3
    4
    unsigned int rnd_func_uniform(void)
    {
      return 1 + sb_rnd() % args.table_size;
    }
  • 完全按随机数从整个table_size取id
  • 这个场景下没有热门数据一说
  • gaussian:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    unsigned int rnd_func_gaussian(void)
    {
      int          sum;
      unsigned int i;
     
      for(i=0, sum=0; i < args.dist_iter; i++)
        sum += (1 + sb_rnd() % args.table_size);
     
      return sum / args.dist_iter;
    }
  • 按高斯分布取id,默认取值范围也是整个tabel_size,默认方差是12,当然方差越高,分布是越集中的.但也会导致结算量大增
  • 这个场景下基本也是没有热门数据一说
  • special:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    unsigned int rnd_func_special(void)
    {
      int          sum = 0;
      unsigned int i;
      unsigned int d;
      unsigned int res;
      unsigned int range_size;
     
      if (args.table_size == 0)
        return 0;
     
      /* Increase range size for special values. */
      range_size = args.table_size * (100 / (100 - args.dist_res));
     
      /* Generate evenly distributed one at this stage  */
      res = (1 + sb_rnd() % range_size);
     
      /* For first part use gaussian distribution */
      if (res <= args.table_size)
      {
        for(i = 0; i < args.dist_iter; i++)
        {
          sum += (1 + sb_rnd() % args.table_size);
        }
        return sum / args.dist_iter;
      }
     
      /*
       * For second part use even distribution mapped to few items
       * We shall distribute other values near by the center
       */
      d = args.table_size * args.dist_pct / 100;
      if (d < 1)
        d = 1;
      res %= d;
     
      /* Now we have res values in SPECIAL_PCT range of the data */
      res += (args.table_size / 2 - args.table_size * args.dist_pct / (100 * 2));
     
      return res;
    }
  • special分布分两部分 100% - oltp-dist-res% 的请求的数据还是按照整个table_size高斯分布进行取id, oltp-dist-res%的请求则是取table_szie*oltp-dist-pct%的数据,并且这些数据都分布在table_size/2周围
  • 这个场景下热门数据是有了即oltp-dist-pct%的数据是热门的,oltp-dist-res%的请求都会走热门数据.但是热门数据的分布并不是离散的,是集中在table_size/2附近.
  • 既然都不符合,那我们就来改一下sysbench让他符合Row Cache的场景.3个场景来说special最符合,只要改一行代码就可以啦
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    unsigned int rnd_func_special(void)
    {
      int          sum = 0;
      unsigned int i;
      unsigned int d;
      unsigned int res;
      unsigned int range_size;
     
      if (args.table_size == 0)
        return 0;
     
      /* Increase range size for special values. */
      range_size = args.table_size * (100 / (100 - args.dist_res));
     
      /* Generate evenly distributed one at this stage  */
      res = (1 + sb_rnd() % range_size);
     
      /* For first part use gaussian distribution */
      if (res <= args.table_size)
      {
        for(i = 0; i < args.dist_iter; i++)
        {
          sum += (1 + sb_rnd() % args.table_size);
        }
        return sum / args.dist_iter;
      }
     
      /*
       * For second part use even distribution mapped to few items
       * We shall distribute other values near by the center
       */
      d = args.table_size * args.dist_pct / 100;
      if (d < 1)
        d = 1;
      res %= d;
     
      /* Now we have res values in SPECIAL_PCT range of the data */
      //res += (args.table_size / 2 - args.table_size * args.dist_pct / (100 * 2));
      res *= (100/args.dist_pct); //这下够离散了
      return res;
    }

        可以直接下载我修改好的包哦

        http://code.google.com/p/row-cache-for-innodb/downloads/detail?name=sysbench-0.4.8.tar.gz&can=2&q=#makechanges

        参考执行命令:

    sysbench --test=oltp --oltp-test-mode=simple  --oltp-skip-trx=on
    --oltp-table-size=80000000  --oltp-range-size=1
    --mysql-host=localhost --mysql-user=xx --mysql-password=xx
    --oltp-read-only=on --init-rng=on --num-threads=70
    --oltp-dist-type=special --oltp-dist-pct=1 --oltp-dist-res=80
    --max-requests=0 --max-time=1800 run

    同分类推荐文章

    1. 使用deepseek进行Oracle恢复,引起重大故障 (2026-06-22 10:56:00)
    2. 接手一个只差临门一脚的数据库恢复 (2026-06-18 00:13:09)
    3. 我做了一个 AI 版的 StarRocks 升级风险扫描工具,直接帮我定位到一个风险 (2026-06-15 01:00:00)

    查看更多 数据库 文章 →

    建议继续学习

    1. 深入浅出INNODB MVCC机制与原理 (累计阅读 9,692)
    2. Innodb IO优化-配置优化 (累计阅读 7,724)
    3. Innodb分表太多或者表分区太多,会导致内存耗尽而宕机 (累计阅读 7,717)
    4. 由浅入深理解索引的实现(2) (累计阅读 7,707)
    5. MySQL中like语句及相关优化器tips (累计阅读 6,279)
    6. Innodb 表和索引结构 (累计阅读 6,224)
    7. InnODB和MyISAM索引统计集合 (累计阅读 6,232)
    8. 从load data引发的死锁说起 (累计阅读 6,141)
    9. 一次神奇的MySQL优化 (累计阅读 6,081)
    10. 性能测试工具sysbench简介 (累计阅读 6,026)