2

首先,这不是问在 SQL 中,count(column) 和 count(*) 有什么区别?.

假设我有一个users带有主键的表user_id和另一个logged_in描述用户现在是否登录的字段。

跑步有区别吗

SELECT COUNT(user_id) FROM users WHERE logged_in=1

SELECT COUNT(logged_in) FROM users WHERE logged_in=1

查看有多少用户被标记为已登录?也许与索引有区别?

如果有特定于数据库的细微差别,我正在运行 MySQL。

4

2 回答 2

12

在 MySQL 中,count 函数不会对 null 表达式进行计数,因此您的两次查询的结果可能会有所不同。正如评论和 Remus 的回答中提到的,这是 SQL 的一般规则和规范的一部分。

例如,考虑以下数据:

user_id   logged_in
1         1
null      1

SELECT COUNT(user_id)在此表上将返回 1,但SELECT COUNT(logged_in)将返回 2。

实际上,问题中示例的结果应该始终相同,只要表构造正确,但使用的索引和查询计划可能会有所不同,即使结果相同。此外,如果这是一个简化的示例,计算不同的列也可能会改变结果。

另请参阅此问题:MySQL COUNT() and nulls

于 2013-01-17T21:13:17.777 回答
5

记录一下:这两个查询返回不同的结果。正如规范所说:

返回SELECT 语句检索的行中 expr的非 NULL值的计数。

您可能会争辩说,给定logged_in=1NULLlogged_in行的条件无论如何都会被过滤掉,并且user_id不会在 table 中包含 NULL users。虽然这可能是真的,但它并没有改变查询不同的基本原理。您要求查询优化器进行上述所有逻辑推论,对您来说它们可能是显而易见的,但对于优化器可能不是。

现在,假设实际上两者之间的结果总是相同的,答案很简单:不要在生产中运行这样的查询(我的意思是它们中的任何一个)。是扫描,无论您如何切片。logged_in基数太低而无关紧要。保留一个计数器,在每次登录和每次注销事件时更新它。它会随时间漂移,根据需要经常刷新(每天一次,每小时一次)。

至于问题本身:SELECT COUNT(somefield) FROM sometable可以使用窄索引就somefield导致更少的IO。建议使用*这个空间,因为优化器可以使用它认为合适的任何索引(但这会因产品而异,具体取决于我们处理的查询优化器的智能程度,YMMV)。但是当您开始添加 WHERE 子句时,可能的替代方案(=要使用的索引)很快就会消失。

于 2013-01-17T21:21:10.807 回答