视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
mysql测试小工具mybench试用
2020-11-09 13:19:44 责编:小采
文档

小型的mysql测试工具,主要有自带的mysqlslap、super-smack和mybench。嗯,我这里的小型的意思是指工具安装过程简单。mysqlslap的使用方法遍地都是,就不先详细写了。根据个人偏好写写mybench吧,毕竟是perl的。安装很简单,如下: cpanm DBI DBD::mysql Tim

小型的mysql测试工具,主要有自带的mysqlslap、super-smack和mybench。嗯,我这里的小型的意思是指工具安装过程简单。 mysqlslap的使用方法遍地都是,就不先详细写了。根据个人偏好写写mybench吧,毕竟是perl的。 安装很简单,如下:

cpanm DBI DBD::mysql Time::HiRes
wget http://jeremy.zawodny.com/mysql/mybench/mybench-1.0.tar.gz
tar zxvf mybench-1.0.tar.gz
cd mybench-1.0
perl MakeFile.PL && make && make install

但是使用就不是太简单了——mysqlslap会自己生成(-a选项)sql,super-smack则带了一个gen-data程序生成数据然后自动导入,但是mybench没有,所以只能自己搞定数据。 不过mybench还是自己生成了一个测试模版的脚本在/usr/bin/bench_example,很简单的就知道怎么做了。 example如下:

#!/usr/bin/perl -w
eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
 if 0; # not running under some shell
use strict;
use MyBench;
use Getopt::Std;
use Time::HiRes qw(gettimeofday tv_interval);
use DBI;
my %opt;
Getopt::Std::getopt('n:r:h:', \%opt);
#这是我见过的最hardcode的perl脚本了(呃,除了我自己写的垃圾),连db库、用户名、密码都不给运行参数的
my $num_kids = $opt{n} || 10;
my $num_runs = $opt{r} || 100;
my $db = "test";
my $user = "test";
my $pass = "";
my $port = 3306;
my $host = $opt{h} || "192.168.0.1";
my $dsn = "DBI:mysql:$db:$host;port=$port";
my $callback = sub
{
 my $id = shift;
 my $dbh = DBI->connect($dsn, $user, $pass, { RaiseError => 1 });
#为测试准备的请求,测select就写select,测insert就写insert呗~
#如果不修改,也就是说测试用的是test.mytable表,而且必须有一个列叫id
 my $sth = $dbh->prepare("SELECT * FROM mytable WHERE ID = ?");
 my $cnt = 0;
 my @times = ();
 ## wait for the parent to HUP me
 local $SIG{HUP} = sub { };
 sleep 600;
#脚本定义的每个进程执行多少次请求
 while ($cnt < $num_runs)
 {
 my $v = int(rand(100_000));
 ## time the query
 my $t0 = [gettimeofday];
#真正的执行sql请求,通过上面的rand知道,之前准备的test.mytable的id列必须是int格式,同时不少于10w行(又一处hard)
 $sth->execute($v);
#通过前后两次gettimeofday获得sql的exec耗时
 my $t1 = tv_interval($t0, [gettimeofday]);
#完成一次请求执行,加入数组
 push @times, $t1;
 $sth->finish();
 $cnt++;
 }
 ## cleanup
 $dbh->disconnect();
#计算本进程全部请求的各项数据,几个大小和均来自MyBench模块
 my @r = ($id, scalar(@times), min(@times), max(@times), avg(@times), tot(@times));
 return @r;
};
#将上面这个函数交给MyBench模块的fork_and_work执行,即并发指定数量请求,返回总的结果
my @results = MyBench::fork_and_work($num_kids, $callback);
#计算总的数据
MyBench::compute_results('test', @results);
exit;
__END__

然后看看/usr/lib/perl5/site_perl/5.8.8/MyBench.pm,主要内容就是fork和compute:

package MyBench;
use strict;
$main::VERSION = '1.0';
use Exporter;
@MyBench::ISA = 'Exporter';
#导出求最大值、最小值、平均值、综合值的函数给外面用
@MyBench::EXPORT = qw(max min avg tot);
sub fork_and_work($$)
{
#关闭
输出缓冲 $|=1; use strict; use IO::Pipe; use IO::Select; $SIG{CHLD} = 'IGNORE'; ## let the kids die my $kids_to_fork = shift; my $callback = shift; my $num_kids = 0; my @pipes = (); my @pids = (); my $pid = undef; print "forking: "; while ($num_kids < $kids_to_fork) { #用IO::Pipe管道方式来传递父子进程的信息 my $pipe = new IO::Pipe; #fork进程开始 if ($pid = fork()) { ## parent $num_kids++; #每fork完成一个打印一个+号 print "+"; #从管道中读取数据 $pipe->reader(); push @pipes, $pipe; push @pids, $pid; } elsif (defined $pid) { ## child #打开管道写入数据的功能 $pipe->writer(); #执行select_example脚本传入的mysql请求测试函数 my @result = $callback->($num_kids); #把结果写入管道 print $pipe "@result\n"; #关闭管道 $pipe->close(); exit 0; } else { print "fork failed: $!\n"; } } print "\n"; ## give them a bit of time to setup my $time = int($num_kids / 10) + 1; print "sleeping for $time seconds while kids get ready\n"; sleep $time; #发送SIGHUP信号给callback函数 kill 1, @pids; ## collect the results my @results; print "waiting: "; #从管道中读取数据到数组 for my $pipe (@pipes) { my $data = <$pipe>; push @results, $data; $pipe->close(); print "-"; } print "\n"; return @results; } sub compute_results(@) { my $name = shift; my $recs = 0; my ($Cnt, $Min, $Max, $Avg, $Tot, @Min, @Max); while (@_) { ## 6 elements per record my $rec = shift; chomp $rec; my ($id, $cnt, $min, $max, $avg, $tot) = split /\s+/, $rec; $Cnt += $cnt; $Avg += $avg; $Tot += $tot; push @Min, $min; push @Max, $max; $recs++; } $Avg = $Avg / $recs; $Min = min(@Min); $Max = max(@Max); my $Qps = $Cnt / ($Tot / $recs); print "$name: $Cnt $Min $Max $Avg $Tot $Qps\n"; print " clients : $recs\n"; print " queries : $Cnt\n"; print " fastest : $Min\n"; print " slowest : $Max\n"; print " average : $Avg\n"; print " serial : $Tot\n"; print " q/sec : $Qps\n"; } ## some numerical helper functions for arrays sub max { my $val = $_[0]; for (@_) { if ($_ > $val) { $val = $_; } } return $val; } sub min { my $val = $_[0]; for (@_) { if ($_ < $val) { $val = $_; } } return $val; } sub avg { my $tot; for (@_) { $tot += $_; } return $tot / @_; } sub tot { my $tot; for (@_) { $tot += $_; } return $tot; } 1;

好了,开始准备数据,比较懒,直接用super-smack的gen-data先出了一些./gen-data -n 100000 -f %n,%80-12s%12n,%512-512s,%d > /root/data,然后进mysql里执行:

USE test;
CREATE TABLE mytable (id INT(11) NOT NULL AUTO_INCREMENT, col1 CHAR(100), col2 CHAR(100), col3 INT(11), PRIMARY KEY (id) )ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOAD DATA LOCAL INFILE 'data' REPLACE INTO TABLE 'mytable' FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';
INSERT INTO mytable (col1,col2,col3) SELECT col1,col2,col3 FROM mytable;

最后执行./select_bench -h 10.168.170.92 -n 10 -r 1000就能看到结果了: forking: ++++++++++ sleeping for 2 seconds while kids get ready waiting: ———- test: 10000 0.00017 0.006809 0.0010413514 10.413514 9602.9063772325 clients : 10 queries : 10000 fastest : 0.00017 slowest : 0.006809 average : 0.0010413514 serial : 10.413514 q/sec : 9602.9063772325

下载本文
显示全文
专题