在Oracle中,当查询行是否存在时,为什么选择Select 1比Select count(*)更快?
在Oracle中,当查询行是否存在时,为什么选择Select 1比Select count(*)更快?
如果RDBMS支持,最好使用EXISTS或等效的方法,这样可以尽早停止处理匹配的行。
由于Oracle在PL/SQL中不支持IF EXISTS,因此CodeByMidnight的建议通常会使用EXISTS来完成类似的操作,例如:
SELECT 1
INTO l_local_variable
FROM dual
WHERE EXISTS(
SELECT 1
FROM some_table
WHERE some_column = some_condition );
Oracle知道只要找到一个匹配条件的行就可以停止处理WHERE EXISTS子句,因此不必计算可能匹配条件的大量行数。当您检查涉及未索引列或可能返回大量行的条件时,这个问题显然就不那么重要了,当然,如果您正在检查特定键值是否存在行,则这样做并不会带来太多问题。
更新:根据原始发布者在评论中提供的澄清,简短而明确的答案是“SELECT 1
”或“SELECT COUNT(1)
”不比“SELECT COUNT(*)
”更快。与您查看的任何编码指南相反,“COUNT(*)”是计算所有行的首选方法。曾经有一个关于“COUNT(1)”更快的老传说。至少在过去十年发布的任何Oracle版本中都不是如此,并且很可能从来没有。然而,这是一个广为人知的信仰。今天,对于使用“COUNT(1)”而不是“COUNT(*)”的代码,我通常怀疑作者容易相信各种Oracle的神话,因此建议使用“COUNT(*)”。
如果select count(*)没有得到有效优化,那我会感到惊讶。因为不需要加载所有的列,也不会有与列相关的处理。
由于星号将所有列计入统计,因此“1”是一种本地数据类型。
在MySQL中,“SELECT COUNT(主键名称)”应该与您的SELECT 1一样快。 它是索引的计数。对索引进行计数应该非常快;)
我认为这对于Oracle来说并不正确。 http://justoracle.blogspot.com/2006/12/count-vs-count1.html
但是,在某些数据库中,原因是因为'*'必须访问表的元数据。这往往会增加不必要的开销。而1只是一个字面量。
其他条件相同的情况下,"select 1 from my_table"
比 "select count(*) from my_table"
更快地返回第一个结果,但如果您检索查询的所有结果,则 count(*)
的速度会更快,因为它涉及的数据要少得多(1个整数,而不是表中每行的1个整数)。
如果您正在使用postgresql,则count(1)
实际上比count(*)
慢。
根据:https://www.citusdata.com/blog/2016/10/12/count-performance/ :
关于
count(1)
与count(*)
的说明。人们可能认为count(1)
会更快,因为count(*)
似乎要查询整个行的数据。然而事实恰恰相反。星号在这里是无意义的,不像在SELECT *
中的用法。PostgreSQL将表达式count(*)
解析为一个特殊情况,不带参数。(历史上,该表达式应该被定义为count()
。)另一方面,count(1)
需要一个参数,PostgreSQL必须在每一行上检查其参数1是否确实不为空。