今天我遇到了一个关于大型套装搜索效率的问题,我最好把它归结为最基本的情况。我觉得这种事情可能与我遗漏的一些经典问题或基本概念有关,所以指向它的指针会很棒。
假设我有一个像
这样的表定义CREATE TABLE foo(
id int,
type bool,
reference int,
PRIMARY KEY(id),
FOREIGN KEY(reference) REFERENCES foo(id),
UNIQUE KEY(reference)
) Engine=InnoDB;
填充n行,其中n / 2随机分配type = 1。每行引用另一个,其类型相同除了第一行,其中reference = null。
现在我们要打印所有类型为1的项目。我假设在某些时候,以递归方式调用类似
的内容会更快function printFoo1($ref){
if($ref==null)
return;
$q = 'SELECT id, reference FROM foo WHERE id='.$ref;
$arr = mysql_fetch_array( mysql_query($q) );
echo $arr[0];
printFoo1($arr[1]);
}
与
相反function printFoo2($ref){
$q = 'SELECT id FROM foo WHERE type=1';
$res = mysql_query($q);
while( $id = mysql_fetch_array($res) ){
echo $id[0];
}
}
这里的要点是函数1搜索“id”,它被索引,而函数2必须进行n / 2次比较而不会产生命中,但是多次查询的开销是明显大于单一的SELECT。
我的假设是否正确?如果是这样,在函数1优于函数2之前,我们需要多大的数据集?
答案 0 :(得分:0)
你的例子有点难以解析,但在顶部开始不好:
你的第一个函数没有返回type = 1的所有元素。它返回所有依赖的元素(基于引用)到你传入的元素。从PHP的角度来看,因为链接/句柄是已经打开,每次连续请求都会产生函数调用的非平凡开销,更不用说字符串连接会在每次执行该行时产生成本。
通常最好使用第二个函数样式,因为它只查询数据库一次,并且将返回您请求的元素而无需进一步的工作。当然,它将归结为一个分析器,以确定哪个会更快地返回,但从我的测试中,第二个是更好的选择:
这是在db中使用n = 5000个元素执行的(n / 2 = 2500类型1,并且从db的查询中传入reference =最高id,类型= 1)。
printFoo1: 3.591840 seconds
printFoo2: 0.010340 seconds
以任何其他方式工作都没有意义。如果您能够做出您的建议,那么JOIN
调用也必须降低效率。
<强>代码强>
$res = mysql_query('SELECT MAX( id ) as `MAX_ID` FROM `foo` WHERE `type` = 1', $link);
$res2 = mysql_fetch_assoc($res);
$id = $res2['MAX_ID'];
// cleanup result and free resources here
echo "printFoo1: ";
$start = microtime(true);
printFoo1($id);
echo microtime(true) - $start;
echo '<br />';
echo "printFoo2: ";
$start = microtime(true);
printFoo2();
echo microtime(true) - $start;
mysql_close($link);
所有这些都在Linux上运行的PHP 5.2.17上进行了测试