【问题标题】:Which is the Fastest method to check Rows existence while fetching?获取时检查行存在的最快方法是什么?
【发布时间】:2017-12-18 14:39:18
【问题描述】:

从以下查询中,哪一个是最优化且使用最快的?

[COUNT(id)]

$SQL = "SELECT name, COUNT(id) as Count FROM names WHERE name = :name";
$row = $stmt->fetch();
if ($data['count'] > 0) {
    while ($row) {
        $name = $row['name'];
    }
} else {
    return;
}

[rowCount()]

$SQL = "SELECT name FROM names WHERE name = :name";
if ($stmt->rowCount() > 0) {
    while ($row = $stmt->fetch()) {
        $name = $row['name'];
    }
} else {
    return;
}

[EXISTS]

$SQLEX = "SELECT EXISTS (SELECT name FROM names WHERE name = :name LIMIT 1)";
if ($stmt->fetchColumn == 1) {
    $SQL = "SELECT name FROM names WHERE name = :name";
    while (row = $stmt->fetch()){
        $name = $row['name'];
    }
} else {
    return;
}

[RAW]

$SQL = "SELECT name FROM names WHERE name = :name";
$row = $stmt->fetch();
if ($row) {
    while($row) {
        $name = $row['name'];
    }
} else {
    return;
}

我也想知道,为什么使用$stmt->fetch()$stmt->rowCount() 可以获取数据,但使用$stmt->fetchColumn 不能?

【问题讨论】:

  • 他们做的事情都略有不同,因此询问哪个最佳或最快是无效的。除此之外,由于它们各自返回一行,最佳或最快实际上是无关紧要的。
  • SELECT 1 FROM names WHERE name = :name ...如果您只关心它的存在,为什么还要选择name。实际上,尽管这都是非常学术的。由于这是 PDO,您应该rowCount 与 INSERT、UPDATE 或 DELETE 查询一起使用 SELECT。
  • @CD001 问题是在一个查询中我想检查行是否存在,如果存在,我定义并使用它。
  • 这个问题的标题具有误导性。从代码中可以明显看出,您不仅需要检查,还需要获取。这是一个不同的故事。
  • 你为什么要在你的例子中添加一个完全没有意义的while?

标签: php mysql sql pdo


【解决方案1】:

首先,如果您在names(name) 上有一个索引,那么所有索引的速度都应该相当。

其次,在您自己的系统上尝试此类性能测试总是值得的。

第三,如果名称在names 表中被声明为唯一(或主键),那么一切都应该很快。

不过,一般来说,确定行是否可用的最快方法是:

SELECT EXISTS (SELECT name FROM names WHERE name = :name)

子查询中的LIMIT 1 是不必要的——EXISTS 停在第一行(无论数据库使用索引还是表扫描)。

一般来说,使用聚合的第一种方法是最差的解决方案。如果没有索引,它将导致读取整个表的全表扫描。第二个可能会也可能不会读取整个表,这取决于数据库是否开始返回可用的匹配行。它也有返回更多数据的缺点。

【讨论】:

  • 这是一个常见的误解。如果您的查询依赖于任何限制器,无论是 EXISTS 还是 LIMIT,那么它在设计上就不是最优的。
  • @YourCommonSense 。 . .这与现实相去甚远,以至于我很难相信有人会相信这一点。有趣的。但是人类有并且仍然有各种荒谬的信念。
  • 好的,我的印象是在这种特殊情况下应该使用唯一索引。但意识到并非总是如此。
  • Second 一个,我总是像你说的那样找到它,给出错误的行号,即使在空表中它有时也会给我值1,最准确的一个是使用@987654328 @ 但是它阻止我在它之后使用fetch(),这是为什么呢?
  • @Toleo 因为你 1) 没有选择任何合理的东西,并且 2) 已经拿到了。
【解决方案2】:

好吧,看来这个问题需要不止一个答案……

如果您只需要检查是否存在,

  • 如果字段有唯一索引,则所有方法都是平等的,但其中一些方法毫无意义。
  • 如果没有唯一索引,则选择 EXISTS

如果您需要获取实际数据并查看是否有任何返回,那么只需选择您的数据并获取它:

  • 如果预计单行中只有一列,则使用 fetchColumn()
  • 如果只需要一行,则使用 fetch()
  • 如果需要多行,则使用 fetchAll()

然后使用结果值来查看您的查询是否返回了任何数据。

因此,如果您最终确定要问什么,这里是最适合您的代码:

$SQL = "SELECT name FROM names WHERE name = :name";
$data = $stmt->fetchAll(PDO::FETCH_COLUMN);
if (!$data) {
    return;
}
foreach ($data as $name) ...

而且 fetchColumn() 没有任何问题,除了你想使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    • 2011-11-26
    • 2016-02-14
    相关资源
    最近更新 更多