递归搜索大型数据集中的索引的性能

时间:2011-06-06 20:57:33

标签: php mysql database

今天我遇到了一个关于大型套装搜索效率的问题,我最好把它归结为最基本的情况。我觉得这种事情可能与我遗漏的一些经典问题或基本概念有关,所以指向它的指针会很棒。

假设我有一个像

这样的表定义
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之前,我们需要多大的数据集?

1 个答案:

答案 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上进行了测试