PDO :: rowCount VS COUNT(*)

时间:2013-10-01 06:53:08

标签: php mysql optimization pdo

我有一个使用PDO的查询,如果行> 1比获取数据

,则先计算行
SELECT * WHERE id=:id
$row=$SQL->rowCount();

if($row>0){
    while($data=$SQL->fetch(PDO::FETCH_ASSOC)){...

    }
}
else{echo "no result";}

SELECT COUNT(*), * WHERE id=:id
$data=fetch(POD::FETCH_NUM);
$row=data[0];


if($row>0){
//fetch data
}
else{echo "no result";}

哪种表现会更好?

第二。问题,如果我在id上设置了索引

哪一个更好COUNT(id)COUNT(*)

5 个答案:

答案 0 :(得分:23)

第一个问题:

使用count COUNT(),服务器(MySQL)内部将以不同方式处理请求。

执行COUNT()时,服务器(MySQL)只会分配内存来存储计数结果。

使用$row=$SQL->rowCount();时,服务器(Apache / PHP)将处理整个结果集,为所有这些结果分配内存,并将服务器置于提取模式,这涉及许多不同的细节,例如锁定。

请注意PDOStatement::rowCount()返回受最后一个语句影响的行数,而不是返回的行数。如果关联的PDOStatement执行的最后一个SQL语句是SELECT语句,则某些数据库可能会返回该语句返回的行数。但是,并不保证所有数据库都有这种行为,不应依赖于便携式应用程序。

在我的分析中,如果你使用COUNT(),那么这个过程将分为MySQL和PHP,如果你使用$row=$SQL->rowCount();,那么对PHP的处理会更多。

因此MySQL中的COUNT()更快。

第二个问题:

COUNT(*)优于COUNT(id)

说明:

mysql中的count(*)函数已经过优化,可以查找值的计数。使用通配符意味着它不会获取每一行。它只能找到计数。所以尽可能使用count(*)

<强>来源:

答案 1 :(得分:14)

事实上,此处既不需要PDO rowCount也不需要COUNT(*)。

  

如果行&gt; 1则获取数据

是一个错误的陈述 在一个设计理智的Web应用程序中(我知道这听起来像是PHP的一个笑话),不必这样做。
最明智的方式是

  • 首先获取
  • 使用提取的数据
  • 如果需要,我们可以使用这个非常获取的数据来查看是否返回了任何内容:

    $data = $stmt->fetch();
    if($data){
        //use it whatever
    } else {
        echo "No record";
    }
    

简单,直接,而且没有像“哪个无用的功能更好”这样的问题。

在您的情况下,假设id是唯一索引,则只能返回一行。因此,您根本不需要while语句。只需使用上面的代码段来获取并判断是否已获取enythin。

如果需要很多行,那么只需将fetch()更改为fetchAll(),然后使用foreach迭代返回的数组:

$data = $stmt->fetchAll();
if($data){
    foreach ($data as $row) {
        //use it whatever
    }
} else {
    echo "No records";
}

请注意,您永远不应选择超出需要的行数。表示您在常规网页上的查询永远不会返回比显示更多的行。

说到问题本身 - 没有任何意义。我无法比较rowCount VS COUNT(*),因为这是无与伦比的事情。这两个功能有着截然不同的目的,不能互换:

  • COUNT(*)会返回一行带有计数的行,只有在需要记录计数的情况下才能使用但是没有记录本身。 如果您需要记录,count(whatever)不会更快或更慢 - 它毫无意义。
  • rowCount()会返回已选择的行数,因此您几乎不需要它,如上所示。

更不用说第二个例子根本不会取任何行。

答案 2 :(得分:1)

性能差异应该忽略为null,因为在这两种情况下只发出一个查询。第二个查询必须为匹配id的每一行获取一个具有相同值的额外列,因此它可能具有大的内存占用量。即使没有COUNT(*)行计数也应该可用,因此您应该使用第一个解决方案。

关于您的第二个问题,COUNT(id)COUNT(*)的AFAIK在id上的索引会更快,因为数据库引擎必须执行范围扫描以检索行中的行在索引列上进行过滤时,问题和范围扫描更快带索引(在您的情况下为id = SOME_ID)。

答案 3 :(得分:1)

Count(id)或count(*)将使用索引扫描,因此性能会更好。 Rowcount仅返回受影响的行,并在插入/更新/删除

时有用

修改 由于编辑的问题是比较Count(id)和count(),因此会略有不同。 Count()将返回受select影响的行数。 Count(列)将返回非空值计数,但由于它是id,因此不会是空列。所以它对这种情况没有任何影响。

答案 4 :(得分:1)

Count(*)会更快。

PDOStatement::rowCount()不能保证根据PDO文档工作:

“并不保证所有数据库都是如此,不应该依赖便携式应用程序。”

因此,在您的情况下,我建议使用count(*)

参见参考: pdostatement.rowcount Manual