问题

通常一个web应用的性能瓶颈在数据库。因为,通常情况下php中mysql查询是串行的。也就是说,如果指定两条sql语句时,第二条sql语句会等到第一条sql语句执行完毕再去执行。这个时候,如果执行2条sql语句,每条执行时间为50ms,全部执行完毕可能需要100ms。既然,主要原因是sql的串行执行导致。那我们是不是可以改变执行方式来提高性能呢?答案是,可以的。我们可以通过异步执行的方式来提高性能。

异步

如果通过异步的方式去执行,可能性能会有很大提升。如果是采用异步的方式,两条sql语句会并发执行,可能就需要60ms就可以执行完毕。

实现

mysqli + mysqlnd。php官方实现的mysqlnd中提供了异步查询的方法。分别是:
mysqlnd_async_query 发送查询请求
mysqlnd_reap_async_query 获取查询结果
这样就可以不必每次发送完查询请求后,一直阻塞等待查询结果了。

实现代码如下:

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?php
  
$host       = '127.0.0.1';
$user       = 'root';
$password   = '';
$database   = 'test';
  
/**
 * 期望得到额结果
 * array(
 *  1 => int,
 *  2 => int,
 *  3 => int
 * )
 */
$result = array(1=>0, 2=>0, 3=>0);
  
//异步方式[并发请求]
$time_start = microtime(true);
$links = array();
  
foreach ($result as $key=>$value) {
    $obj = new mysqli($host, $user, $password, $database);
    $links[spl_object_hash($obj)] = array('value'=>$key, 'link'=>$obj);
}
$done = 0;
$total = count($links);
  
foreach ($links as $value) {
    $value['link']->query("SELECT COUNT(*) AS `total` FROM `demo` WHERE `value`={$value['value']}", MYSQLI_ASYNC);
}
  
do {
  
    $tmp = array();
    foreach ($links as $value) {
        $tmp[] = $value['link'];
    }
  
    $read = $errors = $reject = $tmp;
    $re = mysqli_poll($read, $errors, $reject, 1);
    if (false === $re) {
        die('mysqli_poll failed');
    } elseif ($re < 1) {
        continue;
    }
  
    foreach ($read as $link) {
        $sql_result = $link->reap_async_query();
        if (is_object($sql_result)) {
            $sql_result_array = $sql_result->fetch_array(MYSQLI_ASSOC);//只有一行
            $sql_result->free();
            $hash = spl_object_hash($link);
            $key_in_result = $links[$hash]['value'];
            $result[$key_in_result] = $sql_result_array['total'];
        } else {
            echo $link->error, "\n";
        }
        $done++;
    }
  
    foreach ($errors as $link) {
        echo $link->error, "1\n";
        $done++;
    }
  
    foreach ($reject as $link) {
        printf("server is busy, client was rejected.\n", $link->connect_error, $link->error);
        //这个地方别再$done++了。
    }
} while ($done<$total);
var_dump($result);
echo "ASYNC_QUERY_TIME:", microtime(true)-$time_start, "\n";
  
$link = end($links);
$link = $link['link'];
echo "\n";
结语

mysql数据库对于每个查询请求都是单独启动一个线程进行处理。如果mysql服务器启动线程过多,必然会造成线程切换引起系统负载过高。如果在mysql数据库负载不高的情况下,使用异步查询还是不错的选择。

参考文档

php中mysql数据库异步查询实现的更多相关文章

  1. Mysql数据库使用量查询及授权

    Mysql数据库使用量查询及授权 使用量查询 查看实例下每个库的大小 select TABLE_SCHEMA, concat(truncate(sum(data_length)/1024/1024,2 ...

  2. MySQL数据库的查询缓冲机制

    MySQL数据库的查询缓冲机制 2011-08-10 11:07 佚名 火魔网 字号:T | T 使用查询缓冲机制,可以极大地提高MySQL数据库查询的效率,节省查询所用的时间.那么查询缓冲机制是怎样 ...

  3. MySql数据库慢查询

    一.什么是数据库慢查询? 数据库慢查询,就是查询时间超过了我们设定的时间的语句. 可以查看设定的时间: 默认的设定时间是10秒.也可以自己根据实际项目设定. set long_query_time=0 ...

  4. 更改XAMPP中MySQL数据库的端口号

    更改XAMPP中MySQL数据库的端口号 如果电脑上已安装MySql数据库,还想用XAMPP中自带的数据库就需要更改XAMPP中数据库的端口号,避免和已安装的数据库冲突.本例以更改为3307端口号为例 ...

  5. flink---实时项目----day03---1.练习讲解(全局参数,数据以parquet格式写入hdfs中) 2 异步查询 3 BroadcastState

    1 练习讲解(此处自己没跑通,以后debug) 题目见flink---实时项目---day02 kafka中的数据,见day02的文档 GeoUtils package cn._51doit.flin ...

  6. 一个项目中mysql数据库经常死锁的问题解决记录

    1.问题描述 此项目为一个物流系统,需要使用PDA对货物进行入库.备货.出货等操作,在系统开发测试过程中,经常发现死锁问题. 有这样一种业务场景:仓库对备货单上货进行扫码备货后,点击"完成& ...

  7. MySQL 数据库 分页查询

    在使用MySQL 进行数据库分页查询的时候最主要是使用LIMIT子句进行查询: 首先来看一下LIMIT: LIMIT子句可以用来限制由SELECT语句返回过来的数据数量,它有一个或两个参数,如果给出两 ...

  8. Python 使用PyMySql 库 连接MySql数据库时 查询中文遇到的乱码问题(实测可行) python 连接 MySql 中文乱码 pymysql库

    最近所写的代码中需要用到python去连接MySql数据库,因为是用PyQt5来构建的GUI,原本打算使用PyQt5中的数据库连接方法,后来虽然能够正确连接上发现还是不能提交修改内容,最后在qq交流群 ...

  9. MYSQL数据库学习----查询

    查询语句是MYSQL数据库中用到的最多的语句. 查询语句分为几种 单表查询 集合函数查询 连接查询 子查询 合并查询 正则表达式查询 一:单表查询 SELECT 属性 FROM 表名 [WHERE 查 ...

随机推荐

  1. 使用 /proc 文件系统来访问 linux操作系统 内核的内容 && 虚拟文件系统vfs及proc详解

    http://blog.163.com/he_junwei/blog/static/19793764620152743325659/ http://www.01yun.com/other/201304 ...

  2. acdeream Matrix Multiplication

    D - Matrix Multiplication Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/O ...

  3. IOS文字属性备注

    // Predefined character attributes for text. If the key is not in the dictionary, then use the defau ...

  4. 如何提高android串口kernel log等级

    在 /device/qcom/common/rootdir/etc/init.qcom.rc write /proc/sys/kernel/printk  "6 6 1 7" 第一 ...

  5. Creating Object Library OLB in Oracle D2k Form

    With following steps you can create Object Library (OLB) in Oracle D2k Forms.Step - 1Create a form i ...

  6. CUBRID学习笔记 33 net事务 cubrid教程示例

    conn.BeginTransaction(); string sql = "create table t(idx integer)"; using (CUBRIDCommand ...

  7. Codeforces Round #257 (Div. 2) B

    B. Jzzhu and Sequences time limit per test 1 second memory limit per test 256 megabytes input standa ...

  8. 预习 jQuary

    一.jQuary简介 1.jQuery 库 - 特性 jQuery 是一个 JavaScript 函数库. jQuery 库包含以下特性: HTML 元素选取 HTML 元素操作 CSS 操作 HTM ...

  9. 【T-SQL系列】常用函数—聚合函数

    聚合函数平均值AVG.标准偏差STDEV.方差VAR.最大值MAX.最小值MIN.合计SUM.次数COUNT.极差值MAX-MIN.变异系数STDEV/AVG*100 什么是统计统计 就是通过样本特性 ...

  10. Java Abstract class and Interface

    Abstract Class 在定义class的时候必须有abstract 关键字 抽象方法必须有abstract关键字. 可以有已经实现的方法. 可以定义static final 的常量. 可以实现 ...