场景描述

  • 从全文检索或者缓存中获取ID,根据ID查询数据库获取基础信息,进行页面展示

  • SQL:select * from table where id in(id1,id2,id3...id40)

  • 此种场景的常规方案是将id对应的基础信息在redis中缓存一份,mysql只是做为后端存储。我们做如下测试就是尝试mysql是否可应对这种查询场景。然而根本原因是DBA告诉我,现在MySQL性能已经极其厉害。

数据量说明

  • 1.8亿条数据
  • 使用Oneproxy分为200个数据表(200个表在同一台机器)
  • 因为id是随机的,查询时oneproxy会将查询分散到所有后端MySql

性能指标

  • 并发数
  • 每次查询的响应时间

MySql服务器

  • 腾讯云提供的MySQL服务

mysql的具体配置不在这里列举,即下面的性能报告只是特定场景下的性能分析,不代表mysql的“真实”性能。本文核心是提供一种测试方法,而不是单纯的提供一份数据报告 。

测试程序简介

  • 基础:php、swoole协程
  • 使用协程控制程序的并发数,每个协程中执行一次查询。当一次查询完成,管道通知开始新的查询。

程序代码

mysql_test.php

<?php
ini_set('memory_limit', '1280M'); //协程会耗费较多的内存 define('MAX_MYSQLPOOL_NUM', $argv['1']); //mysql最大连接数,即并发数
define('TESTCOUNT', $argv['2']); //一共的测试次数 $mysqlconf = [
'host' => '127.0.0.1',
'port' => 3307,
'user' => 'root',
'password' => '123456',
'database' => '',
'timeout' => 10
]; Swoole\Coroutine::create(function () use ($mysqlconf) {
$stime = microtime(true); //程序开始时间 $pool = new MysqlPool($mysqlconf);
$chan = new chan(MAX_MYSQLPOOL_NUM); //并发数,协程间使用channel通信 for($i = 1; $i< TESTCOUNT + MAX_MYSQLPOOL_NUM; $i++) {
$chan->push('x');
Swoole\Coroutine::create(function() use($pool, $chan, $i) {
//测试的业务逻辑开始
$conn = $pool->get();
if($conn) {
$sql = "select /* parallel */ * from table where id in (".implode(',', getRandpid()).')';
$time1 = microtime(true);
$conn->query($sql);
$time2 = microtime(true); if($i % intval(TESTCOUNT / 10) == 0) { //输出执行的进度
echo "\n finish $i / ".TESTCOUNT;
}
$pool->put($conn, (($time2 - $time1) * 1000)); //每次查询耗时就不单独做实例,直接修改连接池类做简单统计
} else {
echo "\n connect mysql fail,跳过SQL";
}
//业务逻辑结束
$chan->pop();
});
}
$etime = microtime(true);
echo "\n ============执行结果=============";
echo "\n 并发数量: ".MAX_MYSQLPOOL_NUM;
echo "\n 查询次数: ".TESTCOUNT;
echo "\n 执行总耗时: ".intval($etime - $stime)."秒\n"; echo "\n QPS (查询次数/总耗时) :". intval((TESTCOUNT / ($etime - $stime)));
echo "\n 每次查询耗时平均值:".intval($pool->alltime / TESTCOUNT) ."ms";
echo "\n ============end=============\n";
die;
}); //数据库连接池,https://wiki.swoole.com/wiki/page/852.html
class MysqlPool
{
protected $pool;
private $mysqlconf;
public $alltime; public function __construct($mysqlconf)
{
$this->pool = new SplQueue();
$this->mysqlconf = $mysqlconf;
$this->alltime = 0;
} public function put($mysql, $time = 0)
{
$this->pool->push($mysql);
$this->alltime += $time;
} public function get()
{
//有空闲连接
if (count($this->pool) > 0) {
return $this->pool->pop();
} $mysql = new Swoole\Coroutine\Mysql();
$res = $mysql->connect($this->mysqlconf);
if ($res == false) {
echo "\n connect error info: ".$mysql->error."\n";
return false;
} else {
return $mysql;
}
}
} //随机生成的数字
function getRandpid()
{
for ($i = 0; $i < 40; ++$i) {
$ret[] = rand(1, 185724600);
}
return $ret;
}

测试1:直接连接mysql,查询单表的性能

  • 测试代码:修改以上代码

    • 1:修改mysql配置为直接连接mysql,而不是oneproxy。即端口从3307改为3306

    • 2:“业务逻辑”部分中的SQL改为:

      $sql = "select * from table_10 where id in (".implode(',', getRandpid()).')';
  • 测试指令:

    php mysql_test.php 1 1000 //并发为1,查询1000次
    php mysql_test.php 10 1000 //并发为10,查询1000次
    php mysql_test.php 50 10000 //并发为50,查询10000次
    ...
    php mysql_test.php 500 100000 //并发为500,查询100000次
  • 测试结果:

  • 结果分析:

    根据主键查询单表,mysql的性能基本可以满足正常业务的需求

测试2

  • 说明

    查询oneproxy。因为查询id是随机的,每查一次oneproxy,对应查询的是40个mysql的表。

    即,当oneproxy的并发数为1,mysql的对应并发数是40

  • 测试代码:

    以上提供的代码即为此种情况的代码,无须修改。

  • 测试指令:

    php mysql_test.php 1 1000 //并发为1,查询1000次
    php mysql_test.php 10 1000 //并发为10,查询1000次
    php mysql_test.php 50 10000 //并发为50,查询10000次
    ...
    php mysql_test.php 100 10000 //并发为100,查询10000次
  • 测试结果:

  • 结果分析:

    • 1:OneProxy做为mysql的代理,对查询性能基本0消耗。

      当oneproxy的查询并发为5时,对应mysql的查询并发为200。测试2的结果,并发为5,每次查询耗时30ms。测试1,mysql并发200,每次查询耗时29ms。可得到结论,oneproxy对性能0消耗。
    • 2:每次查询耗时太高,很小流量的业务才能使用此方案。

测试3:后端mysql表分散到多台机器

  • 分到两台,测试结果:

  • 分析:

    mysql分到两台机器。同样并发数时,每次查询耗时能缩短一倍。

  • 推测:

    mysql表分到更多的机器,每次查询耗时能达到测试1的结果,可满足正常的业务需求。

最后,关注性能的同时,也要关注系统的稳定性、开发者的易用性、易维护性。

使用Swoole测试MySQL在特定SQL下的并发性能的更多相关文章

  1. ubuntu下安装与测试mysql

    1.在决定安装mysql之前,要先确定系统是否已经安装mysql. 输入: 1 mysql 结果:说明尚未安装mysql The program 'mysql' is currently notins ...

  2. mysql row日志格式下 查看binlog sql语句

    有时候我们需要使用row作为binlog的日志格式,即配置文件使用了binlog_format= row 参数 这样以来,我们在查看数据库binlog内容时候,就看不到增删改查的具体语句了,在数据库恢 ...

  3. 数据库表设计时一对一关系存在的必要性 数据库一对一、一对多、多对多设计 面试逻辑题3.31 sql server 查询某个表被哪些存储过程调用 DataTable根据字段去重 .Net Core Cors中间件解析 分析MySQL中哪些情况下数据库索引会失效

    数据库表设计时一对一关系存在的必要性 2017年07月24日 10:01:07 阅读数:694 在表设计过程中,我无意中觉得一对一关系觉得好没道理,直接放到一张表中不就可以了吗?真是说,网上信息什么都 ...

  4. SQL注入之DVWA平台测试mysql注入

    今天主要针对mysql常用注入语句进行测试. 测试环境与工具: 测试平台:DVWA,下载地址:http://down.51cto.com/data/875088,也可下载metaspolit-tabl ...

  5. 测试mysql的sql语句预编译效果

    玩Oracle的都比较关注shared pool,特别是library cache,在使用了绑定变量(预编译sql)之后确实能得到很大的性能提升.现在在转Mysql之后特别是innodb很多东西都还能 ...

  6. MySQL在ROW模式下通过binlog提取SQL语句

    Linux基于row模式的binlog,生成DML(insert/update/delete)的rollback语句通过mysqlbinlog -v 解析binlog生成可读的sql文件提取需要处理的 ...

  7. MySQL在默认事务下各SQL语句使用的锁分析

    数据库使用锁是为了支持更好的并发,提供数据的完整性和一致性.InnoDB是一个支持行锁的存储引擎,锁的类型有:共享锁(S).排他锁(X).意向共享(IS).意向排他(IX).为了提供更好的并发,Inn ...

  8. 【夯实Mysql基础】MySQL在Linux系统下配置文件及日志详解

    本文地址 分享提纲: 1. 概述 2. 详解配置文件 3. 详解日志 1.概述 MySQL配置文件在Windows下叫my.ini,在MySQL的安装根目录下:在Linux下叫my.cnf,该文件位于 ...

  9. MySQL与NoSQL——SQL与NoSQL的融合

    来源:http://www.cnblogs.com/sunli/archive/2011/05/11/mysql-nosql.html 写这一篇内容的原因是MySQL5.6.2突然推出了memcach ...

随机推荐

  1. nginx域名跳转技巧

    1.地址重写:访问server_name的时候跳转到http://www.cnblogs.com/qinyujie/ 修改nginx配置文件.加入到server{...}字段或者location字段里 ...

  2. c++ --> 重载、重写(覆盖)和隐藏的区别

    重载.重写(覆盖)和隐藏的区别 一.重载 重载从overload翻译过来,是指同一可访问区内被声明的几个具有不同参数列(参数的类型,个数,顺序不同)的同名函数,根据参数列表确定调用哪个函数,重载不关心 ...

  3. YCSB测试HBase远程完全分布式集群

    写在前面 本文只讲一个很简单的问题,YCSB对HBase集群的测试.虽然网上有很多介绍YCSB测试HBase的文章,但都是针对本地HBase伪分布式集群的.大家都知道,稍微正式一些的压测都会要求测试客 ...

  4. [日常] AtCoder Beginner Contest 075 翻车实录

    别问我为啥要写一篇ABC的游记... 周日打算CF开黑于是就打算先打打ABC找回手速... 进场秒掉 $A$ 和 $B$ , 小暴力一脸偷税 然后开 $C$ ...woc求桥? 怎么办啊我好像突然忘了 ...

  5. JavaScript简史

    JavaScript诞生于1995年. 当时的web正在日益兴起,人们对客户端语言的需求也越来越强烈.当时走在技术革新最前沿的Netscape公司决定开发一种客户端语言,用来处理简单的输入验证. 当时 ...

  6. alpha冲刺第五天

    一.合照 二.项目燃尽图 三.项目进展 调整了一些界面的布局 细化了部分小功能的界面 注册界面和服务器响应了,但是在insert数据库方面出现了错误 四.明日规划 继续研究如何将注册的内容插入数据库 ...

  7. SQLSERVER2012的分页新功能

    SQLSERVER2012的分页新功能 简介 SQL Server 2012中在Order By子句之后新增了OFFSET和FETCH子句来限制输出的行数从而达到了分页效果.相比较SQL Server ...

  8. 项目Alpha冲刺Day9

    一.会议照片 二.项目进展 1.今日安排 侧栏及相关刷新完成,项目结构小变动.个人信息和修改密码后台完成. 2.问题困难 前后台联调出现问题,配置修改了半天还没改好.好像是会话丢失,初步判断应该是后台 ...

  9. 冲刺NO.9

    Alpha冲刺第九天 站立式会议 项目进展 项目已完成模块的模块测试工作开始进行.如学生基本信息模块和学生信用信息模块. 问题困难 框架的掌握存在一定的问题,导致项目的执行速度变慢.其他课程的作业占据 ...

  10. JAVA序列化基础知识

    1.序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来.虽然你可以用你自己的各种各样的方法来保 存object states, ...