21

我有一个使用 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(*)

4

5 回答 5

24

第一个问题:

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

这样做COUNT()时,服务器(MySQL)将只分配内存来存储计数的结果。

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

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

根据我的分析,如果使用COUNT(),则处理将分为 MySQL 和 PHP,而如果使用$row=$SQL->rowCount();,则处理更多的是 PHP。

因此COUNT()在 MySQL 中更快。

第二个问题:

COUNT(*)好于COUNT(id)

解释:

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

资料来源:

于 2013-10-01T07:06:00.447 回答
14

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

如果行 >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";
}

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

说到问题本身——这没有任何意义。无法比较 rowCountVS COUNT(*),因为它是无与伦比的事情。这两个函数的用途完全不同,不能互换:

  • COUNT(*)返回带有计数的单行,并且仅在需要记录计数但不需要记录本身时才使用。
    如果你需要记录,count(whatever)不是更快也不是更慢 - 这是没有意义的。
  • rowCount()返回已选择的行数,因此您几乎不需要它,如上所示。

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

于 2013-10-01T07:42:49.943 回答
1

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

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

于 2013-10-01T07:02:32.620 回答
1

Count(*)会更快。

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

“不保证适用于所有数据库,不应依赖于可移植应用程序。”

所以在你的情况下,我建议使用count(*).

参见参考: pdostatement.rowcount 手册

于 2013-10-01T07:06:25.473 回答
1

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

关于您的第二个问题,AFAIK 或者COUNT(id)索引COUNT(*)on 会更快id,因为数据库引擎必须执行范围扫描来检索有问题的行,并且在索引列上过滤时范围扫描更快(在您的案例id = SOME_ID)。

于 2013-10-01T07:00:47.093 回答