MySQL 自定义存在查询性能
MySQL customized exists query performance
由于使用 Hibernate,我无法使用这样的 exists 编写 JPA 查询(我将其翻译为纯 SQL 查询):
SELECT EXISTS (SELECT * FROM account WHERE activated = true)
所以我必须编写一个替代查询来检查是否存在已激活的帐户。看了这个网站上的几个建议后,我看到了一个替代品:
select case when count(*)> 0 then true else false end from account where activated = true
我的问题是:这对性能不好吗,是短路查询吗。表示如果发现至少一个激活的帐户,查询是否停止执行?或者它必须获得所有激活的帐户然后在最后检查总结果是否大于零?
(这些评论特定于 MySQL with InnoDB。)
EXISTS()
运行直到找到匹配的第一行。 COUNT()
必须找到所有匹配项。因此,EXISTS
至少与 COUNT
一样快,可能快得多。
EXISTS
returns true
或 false
a > b
returns true
或 false
COUNT(*)
returns 0
或超过 0
;见下文
a = true
与a
效果相同
我的观点是:你不需要做任何类似 ...then true else false...
您可能会看到 false
为 0
,true
为非零值。也就是说,> 0
也是不必要的(在您的示例中)。
对于您的具体问题,优化器不够智能,无法将 COUNT(*)>0
转换为 EXISTS
。
您的查询似乎很深入,为什么不只是一个简单的
select count(*)
from account
where activated = true
完成,您将返回一条记录并进行计数。但是,如果您只是想看看是否有任何帐户被激活,您所需要的只是
select 1
from account
where activated = true
limit 1
在这里,您强制限制为 1,因此一旦找到第一个符合条件的查询,查询就完成了,您可以继续 - 即使您的数据库有 1000 条(甚至数百万条)记录。
由于使用 Hibernate,我无法使用这样的 exists 编写 JPA 查询(我将其翻译为纯 SQL 查询):
SELECT EXISTS (SELECT * FROM account WHERE activated = true)
所以我必须编写一个替代查询来检查是否存在已激活的帐户。看了这个网站上的几个建议后,我看到了一个替代品:
select case when count(*)> 0 then true else false end from account where activated = true
我的问题是:这对性能不好吗,是短路查询吗。表示如果发现至少一个激活的帐户,查询是否停止执行?或者它必须获得所有激活的帐户然后在最后检查总结果是否大于零?
(这些评论特定于 MySQL with InnoDB。)
EXISTS()
运行直到找到匹配的第一行。 COUNT()
必须找到所有匹配项。因此,EXISTS
至少与 COUNT
一样快,可能快得多。
EXISTS
returns true
或 false
a > b
returns true
或 false
COUNT(*)
returns 0
或超过 0
;见下文
a = true
与a
我的观点是:你不需要做任何类似 ...then true else false...
您可能会看到 false
为 0
,true
为非零值。也就是说,> 0
也是不必要的(在您的示例中)。
对于您的具体问题,优化器不够智能,无法将 COUNT(*)>0
转换为 EXISTS
。
您的查询似乎很深入,为什么不只是一个简单的
select count(*)
from account
where activated = true
完成,您将返回一条记录并进行计数。但是,如果您只是想看看是否有任何帐户被激活,您所需要的只是
select 1
from account
where activated = true
limit 1
在这里,您强制限制为 1,因此一旦找到第一个符合条件的查询,查询就完成了,您可以继续 - 即使您的数据库有 1000 条(甚至数百万条)记录。