PHP:帮助执行一系列查询

时间:2010-10-15 13:30:24

标签: php sql mysql

我有一个循环遍历满足某个条件的表的所有行的方法,然后检查该行中的一个列是否出现在文本中。方法如下:

public function isRecipeType($ingredients, $type)
{
    $rows = $this->fetchAll($this->select()->where("type = ?", $type));

    foreach($rows as $row)
    {
        if((strpos($ingredients, $row->name)) !== false)
        {
            return true;
        }
    }
}

但这需要永远。如何加快速度(不从表中删除行)?

3 个答案:

答案 0 :(得分:3)

您尝试解决的问题可以表示为“是否存在任何行,类型= X,其名称包含文本Y?”

这是数据库可以回答的问题,无需在PHP中编写循环。使用数据库更快,数据库可以访问有关调优的更多信息。基本上将匹配该类型的表的整个子集从数据库(可能通过网络)下载到PHP处理器以回答查询是低效的。让DB为您完成工作。它也更容易阅读,因为SQL是一种声明性语言,而不是PHP解决方案必不可少。

public function isRecipeType($ingredients, $type)
{
    $sql = "SELECT COUNT(*) AS c ".
           "FROM table ".
           "WHERE type = ? ".
           "   AND ? LIKE CONCAT('%', name, '%')";
    $rows = execute($sql, $type, $ingredients);
    $row = $rows[0];
    return $row["c"] > 0;
}

这使用MySQL语法,如果您使用另一个数据库,则用

替换SQL的最后一行
           "   AND ? LIKE '%' || name || '%'";

我在你的代码中发明了一个execute方法,我不知道你正在使用什么数据库访问层,但毫无疑问你可以访问类似的东西。

如另一个答案所示,请确保type列上有索引。然后,此语句的执行计划将是:查找具有匹配类型的所有行(使用索引),然后浏览数据并应用LIKE。

除非超过例如10%的行与类型列匹配,然后对所有数据的顺序读取(即不使用索引)将比使用索引识别行然后随机访问读取它们更快。但是数据库会知道是否是这种情况,创建索引并没有坏处,然后数据库可以根据这个标准使用它。

答案 1 :(得分:2)

首先,您是否在type列上定义了索引?由于这是您搜索中唯一的条件,因此您希望它是一个有效的条件。

答案 2 :(得分:2)

你不能用SQL做一切吗?

已更正 - 未经测试 - 例如:

"... WHERE `type`=? AND FIND_IN_SET(name, `$ingredients`) > 0 LIMIT 1"

// return TRUE if a row is found

要使FIND_IN_SET生效,必须用逗号分隔值,这样您就可能需要转换$ingredients变量。