PHP + Mysql多个表并行查询如何实现
select * from databasea.table1 union select * from databaseb.table2 ;
不推荐垮库使用.弊端太多
select c.name from 收藏表 a,用户表 c where a.user_id = c.user_id
在PHP-FPM处理HTTP请求时,有时会遇到一个请求需要进行多次MySQL查询(在报表类应用中比较常见)。通常我们会以串行方式查询:
$link = new mysqli();
$rs1 = $link->query('SELECT * FROM table1');
while ($row = $rs1->fetch_row()) { ... }
$rs2 = $link->query('SELECT * FROM table2');
while ($row = $rs2->fetch_row()) { ... }
$rs3 = $link->query('SELECT * FROM table3');
while ($row = $rs3->fetch_row()) { ... }
串行查询方式有个缺点:在MySQL返回数据之前,PHP一直是处于空等的状态,不会继续往后执行。如果数据量大或者查询复杂,MySQL响应可能会比较慢,那么以串行方式查询会有一些延迟。给用户最直接的感受就是 Loading… 的圈圈一直打转。
那么有什么办法可以减少查询MySQL的时间?用多进程并行查询不行,因为PHP-FPM 中不允许用 pcntl_fork 一类的调用。
幸好还有 mysqlnd,mysqlnd提供了类似 stream_select 的机制(见 这篇文章) ,可以做到在单进程中对MySQL并行查询。这主要运用了mysqli_poll 和 reap_async_query 两个函数。
还是通过例子来介绍MySQL并行查询的实施方法。假设要并行地向MySQL发出10个查询,最基本的代码应该是这样的:
1. $links = [];
2. for ($i = 0; $i !== 10; $i++) {
3. $links[$i] = new mysqli('127.0.0.1', 'user', 'password', 'db1');
4. $links[$i]->query('SELECT SLEEP(1)', MYSQLI_ASYNC);
5. }
6. $allResult = [];
7. while (!empty($links)) {
8. $reads = $links;
9. $errors = $reject = [];
10. if (!mysqli_poll($reads, $errors, $reject, null)) {
11. continue;
12. }
13. foreach ($reads as $read) {
14. $idx = array_search($read, $links, true);
15. $allResult[$idx] = [];
16. $result = $read->reap_async_query();
17. while ($row = $result->fetch_row()) {
18. $allResult[$idx][] = $row;
19. }
20. $read->close();
21. unset($links[$idx]);
22. }
23. }
解释下这段代码的含义:
2~5行,同时发起10个MySQL连接,并发出查询
注意query() 的第二个参数带上了 MYSQLI_ASYNC 表示非阻塞查询
10行,使用mysqli_poll 轮询10个连接的查询有无返回
mysqli_poll 的第一个参数$reads是个数组,包含需要轮询那些连接。mysqli_poll 执行完后,会改写$reads,改写后$reads包含的是那些已经有数据返回连接。
mysqli_poll的第四个参数,控制的是轮询的等待时间,单位是“秒”。如果像本例当中设置为null,那么mysqli_poll轮询是阻塞的:只有监听的连接中,任意一个连接有数据返回了,mysqli_poll才会返回。如果等待时间设置为0,那么每次执行mysqli_poll会立即返回,外层的while会频繁循环。
第11~19行,遍历已经有数据返回的连接
reap_async_query和普通query一样,返回的是mysqli_result,可以一行行fetch数据
20~21行,对于已经获得了数据的连接,下次mysqli_poll就不需要再轮询这个连接了,所以关闭连接,并从$links数组删除这个连接
当所有的连接都返回了数据,$links数组空了,while循环也就终止了。
使用并行查询的方式,可以大大缩短处理HTTP请求的时间,假设本例中的10个SQL查询,每个需要执行1秒。因为是并行,处理所有的查询,也只需要1秒左右。
李浩天立: 比如联合A B俩表 select a.*,b.* from A as a left join B as b on a.id = b.id where a.name='lilei' and b.age=27 order by a.id group by a.class limit 10 ; 很简单
保亭黎族苗族自治县18459743492: PHP,mysql中,我想在多个表中查询一个字段 - ?
李浩天立: 前提所有表在一个数据库 不在一个数据库时 自己在变变 <?php $arr=array("index_news","college_news","learning_news","party_news","social_news ");$conn = @mysql_connect("localhost", "你的用户名", "你的密码"...
保亭黎族苗族自治县18459743492: mysql,php, 两个数据库中表联查问题 - ?
李浩天立: 两个库属于两个资源,应该是不能联查的吧. 测试了一下 可以的 只要在表名前面加上库名就可以了 完全独立的站点的话,可以在其中一个上写个接口页,接受一个ID值输出一些查询结果,然后在另一外页抓取下上面的输出内容,做一下整合,相当于接一起了.
保亭黎族苗族自治县18459743492: PHP mysql俩表联查 一张表的多个字段对应另一张表的单个字段 查询出值 - ?
李浩天立: select fields from 另一张表 as 另一张表 left join 一张表 as 一张表 ON 一张表.field=另一张表.field where 条件 我最多的SQL语句用jion写过100多行,才两张表,随便怎么查都行啦
保亭黎族苗族自治县18459743492: 用PHP+mysql查询两个表,然后怎么样把已经查出来的两个数组合并在一起,两张表里有一个相同的字段 - ?
李浩天立: 楼主可以用curl_exec() 从一个页面访问另外一个页面 拿到你的json 然后 json_decode一下 然后跟你本地的进行对比就好了
保亭黎族苗族自治县18459743492: PHP+MYSQL 查询结果作为条件再查另一个表,怎么弄? - ?
李浩天立: 方法一:很简单,再查询一次就好了,代码如下<?php while ($row_Recordset1 = mysql_fetch_assoc($Recordset1)) {$sql = "select * from 表A where userid={$row_Recordset1['user_id']} limit 1";$query = mysql_query($sql);$user = mysql_fetch_...
保亭黎族苗族自治县18459743492: (PHP)MySQL三张表或者多张表关联查询 - ?
李浩天立: SELECT aid,a1,a3,B.*,C.* FROM A LEFT JOIN B ON aid=b_aid INNER JOIN C ON aid=c_aid 你也可以 create view xx as SELECT aid,a1,a3,B.*,C.* FROM A LEFT JOIN B ON aid=b_aid INNER JOIN C ON aid=c_aid
保亭黎族苗族自治县18459743492: php mysql 多表查询 - ?
李浩天立: $sql = "select gjd_callback.call_fee, gjd_callback.call_time from gjd_callball,gjd_cs where gjd_cs.id=gjd_callback.call_id and gjd_cs.id=$id" 还可以:$sql = "select gjd_callback.call_fee, gjd_callback.call_time from gjd_callball left join gjd_cs ongjd_cs.id=gjd_callback.call_id where gjd_cs.id=$id" 这两句都可以!
保亭黎族苗族自治县18459743492: php mysql用一个sql语句查询多个表怎么写 - ?
李浩天立: union all试下
保亭黎族苗族自治县18459743492: php读取mysql中多个表的方法???
李浩天立: 首先b和c要有外键关系,如果想写入的话需要开启事务,同时插入或者更新2个表,要是查询的话就简单的外联就ok了