在PHP中查询MySQL数据表是最常用的操作,但一张表中的数据往往不够用,需要关联另一个表或多个表,这时一般有两种选择:
- 在查询时合并需要用到的数据表->处理数据(合并查询)
- 先查询一个表,获取到相关字段->遍历并查询其它表->处理数据(遍历查询)
这里简单做了下测试,以便对比。
测试环境
| * |
* |
| 服务器 |
Apache(本地) |
| MySQL环境 |
服务器环境 |
| MySQL版本 |
5.6.16 |
| 总字段数 |
184个(2张表) |
| 查询字段数 |
17个 |
| 查询次数 |
10个 |
测试方法
这里用了ThinkPHP3.2.3来进行查询。由于php没有对毫秒级时间戳的原生支持,所以还需封装一个方法来实现:
1 2 3 4 5
| function getMillisecond() { list($t1, $t2) = explode(' ', microtime()); return (float)sprintf('%.0f', (floatval($t1) + floatval($t2)) * 1000); }
|
合并查询的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| $startTime = getMillisecond();
$list = $Model->table('table1') ->alias('t1') ->join('table2 t2 ON t1.id=t2.id') ->field($fields) ->where($map) ->order('update_time desc') ->limit(5) ->select(); $data = array(); foreach ($list as $key=>$val) { array_push($data, $val); } $endTime = getMillisecond();
echo ($endTime - $startTime).'ms';
|
遍历查询的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| $startTime = getMillisecond();
$list1 = M('table1') ->alias('t1') ->field($fields['t1']) ->where($map) ->order('update_time desc') ->limit(5) ->select(); $data = array(); foreach ($list1 as $key=>$val) { $list2 = M('table2') ->alias('t2') ->field($fields['t2']) ->where(array('id'=>$val['id'])) ->find(); $lists = array_merge($val, $list2); array_push($data, $lists); } $endTime = getMillisecond();
echo ($endTime - $startTime).'ms';
|
需要注意的是,遍历查询需要把$fields改写为二维数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| $fields = array( 't1.xxx as xxx', 't2.xxx as xxx', );
$fields = array( 't1'=>array( 'xxx as xxx', ), 't2'=>array( 'xxx as xxx', ) );
|
测试结果
分别对不同的数据量进行了测试
limit(5):
| 查询方式 |
合并查询 |
遍历查询 |
| 最快耗时(ms) |
962 |
754 |
| 最慢耗时(ms) |
1440 |
1448 |
| 平均耗时(ms) |
1201 |
1101 |
limit(15):
| 查询方式 |
合并查询 |
遍历查询 |
| 最快耗时(ms) |
1904 |
1880 |
| 最慢耗时(ms) |
2371 |
3078 |
| 平均耗时(ms) |
2137.5 |
2479 |
limit(30):
| 查询方式 |
合并查询 |
遍历查询 |
| 最快耗时(ms) |
3392 |
3583 |
| 最慢耗时(ms) |
3861 |
5444 |
| 平均耗时(ms) |
3626.5 |
4513.5 |
从数据上看,在数据量不多时,两种查询方式差距不大,甚至遍历查询要快一些。但当数据量越来越大时,合并查询的性能优势就显现出来了。这也很容易理解,因为循环查询时虽然单次的量不多,但须多次连接数据库。如果数据库不在本地服务器,就会增加一定的时间成本。
而且从写法上看,合并查询显得优雅美观一些。因此,如果数据量比较大时,尽量避免遍历查询。