最近大牛 姜承尧 也在测试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个场景的实现
1
2
3
4 |
unsigned int rnd_func_uniform(void)
{
return 1 + sb_rnd() % args.table_size;
} |
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;
} |
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;
} |
既然都不符合,那我们就来改一下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;
} |
可以直接下载我修改好的包哦
参考执行命令:
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