获取时检查行存在的最快方法是啥?
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 服务器上拥有数百万用户时,存储和获取图像的最快和最有效的方法是啥?