查询将返回 0 行时的选择计数与选择语句性能

Posted

技术标签:

【中文标题】查询将返回 0 行时的选择计数与选择语句性能【英文标题】:Select count vs select statement performance when the query will return 0 rows 【发布时间】:2020-08-06 14:49:25 【问题描述】:

我正在查看一位老开发人员编写的一些代码,他已不在身边。我发现了一些我不太确定是否有意义的事情,但我认为我没有足够的知识或足够好的 google fu 来找到答案,所以这里是:

代码如下:

var queryCount = SELECT COUNT(Col1) FROM MyTable WHERE ColumnInIndex = 'SomeValue'

if(queryCount == 0)
   return [];

var results = SELECT Col1, Col2, Col3,... FROM MyTable WHERE ColumnInIndex = 'SomeValue'
return results;

所以我的第一个想法是这似乎是多余的,应该首先使用选择查询的结果。我挖得更远了,因为提交建议它进行性能调整。

据我从谷歌搜索得知,count 实际上会更快,因为它不必返回任何数据或提取任何行,并且可以完全依赖索引。

但是,在我上面编写的伪代码中,where 子句不返回任何行的情况似乎不会提高性能,因为 count 和 select 都不会返回任何结果。另外,当有实际结果时,我们会执行其中两个查询,而不仅仅是一个。

此外,由于我们首先使用的是行,因此我们应该只在一次查询中获取数据,而不是两次访问数据库。

我完全不在这儿吗?

我们正在使用 mysql v5.6.46

【问题讨论】:

查询编写时使用 * 没关系。但在生产环境中从未使用过 SELECT *。总是使用必需的列名。因为它也会影响你的表现。除此之外,我从您的第一个查询中了解到的是,如果您使用的是 COUNT(),那么如果没有找到记录,它将给您 0。但是如果您使用的是 SELECT column_1,那么它会给您 null。所以,根据你的条件。我觉得使用 SELECT column_1。这将返回空白 Null @PTank 感谢您的回答,我已从查询中删除 *,因为代码实际上没有它,它只是编写不佳的示例代码。我不太担心 null vs 数组检查,因为这一切都包含在一个适当处理类型检查的 ORM 中,我刚刚用它们转换为的 sql 替换了 ORM 调用。我在这里的问题更多是关于预先进行额外计数查询的性能影响以及是否会提高性能或降低性能。 【参考方案1】:

你是对的。 [但是要一直读到最后!]

两步是低效的——在任何版本的 MySQL 中。如果有零行,优化器将对SELECT 执行基本相同的工作量。

如果有一些行,那么第一个SELECT 是浪费时间。请参阅编程首字母缩写词“KISS”。

伪代码暗示'return'是一个空数组;我假设当没有匹配的行时,任一查询都是这种情况?

附注:我希望ColumnInIndex 的意思是“在某个索引中第一个的列”。如果列不是第一列,则两个查询都不会使用索引。 (此评论不影响主要问题。)

另一个旁注(针对 PTank):当没有匹配的行时,这些都没有

SELECT col FROM ... WHERE ...
SELECT  *  FROM ... WHERE ...

返回任意行;他们不会为列返回NULL。 (* 的使用是“不好的”,原因与原始问题无关。)

哦,又是一条评论。 COUNT(col) 在计算行之前检查 col 是否为非 NULL。 COUNT(*) 只计算行数。在几乎所有情况下,您都应该使用COUNT(*);它更简单,更快,并且可能给出相同的答案。 (如果colPRIMARY KEY,答案将是相同的。)

好心疼!!这意味着您的第一个查询不是多余的!奇怪的情况是col1每一行 中是NULL。第一个查询将返回零计数,但第二个查询将返回一些行(第一列 NULL)。

这是一个棘手的问题吗?

【讨论】:

我应该将其保留为 SELECT COUNT(*),因为它是 ORM 翻译的方式。查询肯定使用索引 - 我们会知道它们是否不是:D - 我认为部分混淆是我尝试抽象出这种格式的代码。为了确认,第二个 sql 语句中空选择的返回也将是一个空数组。感谢您确认我的怀疑,我只是想要一个健全性检查,因为我没有找到关于优化器将如何处理两个查询之间的 0 行的答案(我确信通过正确的搜索,答案就在那里) @Corey - 简化/抽象很方便,但可能适得其反! @Corey - 我无法解决“空”选择 vs 数组 - 哪种客户端语言?什么 API 等等。(抽象化再次成为障碍。)我所知道的所有 API 都将它们等同起来。 PS,EXISTS ( SELECT 1 ... ) 是这个主题的另一个变体。它有优点,但在本例中没有。 PPS -- 1 个命令,即使复杂,也可能比 2 个命令快 -- 因为 any 命令的开销。 (接收、解组、解析、优化、编组、发送。)

以上是关于查询将返回 0 行时的选择计数与选择语句性能的主要内容,如果未能解决你的问题,请参考以下文章

PHP Mysqli - 结果为0时选择*或选择计数(*)?

选择多列的大查询没有返回行时如何返回一些预定义的值

如果第一次选择返回 0 计数,则返回备用视图结果

仅在选择返回有效行时,仅插入到表中

MySQL 选择计数与 EXISTS

选择 Count Where Values 大于 0 SQL Server