mysql left join 与 php foreach 的比较

张映 发表于 2010-02-21

分类目录: php

标签:, , , , ,

一,困惑引发的郁闷

一直做php开发,也没有注意一个问题,那就是多表操作时,到底是用mysql的联合查寻把数据一次都取出来快,还是把各各表里面的数据分别取出来,然后用php的循环来进行查找快,我想很多做php的同行们,也许想过这样的问题,但是有没有实践,去测试一下呢。因为这事,我与以前公司的同事还争执过,在这儿我会把我的测试结果,展示给大家,大家可以亲自实验一下。

二,准备二张表关系表,各加上十条测试数据

1)第一张表

CREATE TABLE IF NOT EXISTS `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`sex` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

-- 以下是数据

INSERT INTO `test` (`id`, `name`, `sex`) VALUES
(1, 'tank', 1),
(2, 'janery', 1),
(3, 'tom', 0),
(4, 'cici', 0),
(5, 'crazy', 1),
(6, 'andy', 0),
(7, 'lading', 0),
(8, 'liady', 0),
(9, 'hunk', 1),
(10, 'celia', 0);

1)第二张表

CREATE TABLE IF NOT EXISTS `testslave` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parentid` int(11) NOT NULL,
`mobile` int(11) NOT NULL,
`email` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

-- testslave里面的数据

INSERT INTO `testslave` (`id`, `parentid`, `mobile`, `email`) VALUES
(1, 1, 123456, 'janery@test.com'),
(2, 2, 46346534, 'tom@test.com'),
(3, 3, 1542345263, 'cici@test.com'),
(4, 4, 56856799, 'crazy@test.com'),
(5, 5, 15423523, 'andy@test.com'),
(6, 6, 43261664, 'lading@test.com'),
(7, 7, 847534523, 'liady@test.com'),
(8, 8, 13634567, 'hunk@test.com'),
(9, 9, 909202345, 'celia@test.com'),
(10, 10, 987653212, 'tank@test.com');

三,准备二个php文件

1)第一个php文件

<?php
/*
* Created on 2009-12-8
*
* To change the template for this generated file go to
* Window - Preferences - PHPeclipse - PHP - Code Templates
*/

$dsn = 'mysql:dbname=test;host=localhost;port=3306';
$user = 'root';
$password = '';

try {

$dbh = new PDO($dsn, $user, $password);

$sql = "SELECT a.id, a.name, a.sex, b.mobile, b.email".
" FROM test a".
" LEFT JOIN testslave b ON a.id = b.parentid";

$sth = $dbh->prepare($sql);
$sth->execute();

$result = $sth->fetchAll(PDO::FETCH_ASSOC);
print_r($result);

} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}

?>

2)第二个php文件

<?php
/*
* Created on 2009-12-8
*
* To change the template for this generated file go to
* Window - Preferences - PHPeclipse - PHP - Code Templates
*/

$dsn = 'mysql:dbname=test;host=localhost;port=3306';
$user = 'root';
$password = '';

try {

$dbh = new PDO($dsn, $user, $password);

$sql = "SELECT id, name, sex from test ";
$sql_slave = "SELECT parentid,mobile,email from testslave ";

$sth = $dbh->prepare($sql);
$sth->execute();

$result = $sth->fetchAll(PDO::FETCH_ASSOC);

$sth_slave = $dbh->prepare($sql_slave);
$sth_slave->execute();

$result_slave = $sth_slave->fetchAll(PDO::FETCH_ASSOC);

foreach($result as $k=>$tmp){
foreach($result_slave as $tmp_slave){
if($tmp['id'] == $tmp_slave['parentid']){
$result[$k]['mobile']=$tmp_slave['mobile'];
$result[$k]['email']=$tmp_slave['email'];
}
}
}
print_r($result);

} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}

?>

四,测试结果,及其分析

用mysql的left join 的测试结果

用mysql的left join 的测试结果

用php的foreach的测试结果

用php的foreach的测试结果

由上面二个图,我有以下几点想法:

1.用mysql的left join 比用php的foreach要好一点

2.从开发者的开发效率来看,用mysql的left join比php的循环,要高很多很多。

3.换个角度思考一下,如果用php的循环好一点的话,那么何必要数据库,搞个文本数据库不就可以,直接对文件进行操作,其不更好,把文件的权限控制好,我想比mysql要安全些吧。哈哈。

4.经验很重要,但是有的时候,还是要具体数据来说话。

5.尽量不要太多的表进行联合查寻,二,三张表的联合查寻还可以接受,如果太多表进行联合查寻,会很慢的,所以设计数据库时尽量避免。php的循环也一样,二层循环是可以接受的,如果你有三层循环,运算起来也会很慢。



转载请注明
作者:海底苍鹰
地址:http://blog.51yip.com/php/268.html

4 条评论

  1. 彭军 留言

    $sql = "SELECT a.id, a.name, a.sex, b.mobile, b.email FROM test as a,testslave as b WHERE a.id = b.parentid";   我喜欢这么写联合查询。不知道mysql解析起来是不是比left join 慢呢?

  2. 张映 留言

    你可以把他们二个都测试一下,比较一下就知道了。

  3. justtest 留言

    你有没有测试过1000条数据的情况?

  4. chao 留言

    数据库left jion是优化过的,但偶尔跨库join可以直接使用程序循环