获取时检查行存在的最快方法是啥?

Posted

技术标签:

【中文标题】获取时检查行存在的最快方法是啥?【英文标题】: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? 【参考方案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() 没有任何问题,除了你想使用它。

【讨论】:

以上是关于获取时检查行存在的最快方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

从命令行获取一组数字的平均值的最快方法是啥?

在 python 或 spark 中获取大数据缺失值的最快方法是啥?

当您在 LAMP 服务器上拥有数百万用户时,存储和获取图像的最快和最有效的方法是啥?

扁平化深度嵌套的 JSON 以获取 Dataframe 的最快和通用方法是啥?

获取 GameObject 参考的最快方法是啥?

获取数组第一项的最快方法是啥? [复制]