【发布时间】:2011-05-14 07:53:24
【问题描述】:
在阅读一些与 SQL Tuning 相关的文档时,我发现了这一点:
SELECT COUNT(*):
- 计算行数。
- 通常不恰当地用于验证记录的存在。
SELECT COUNT(*) 真的那么糟糕吗?
验证记录存在的正确方法是什么?
【问题讨论】:
标签: sql optimization query-optimization
在阅读一些与 SQL Tuning 相关的文档时,我发现了这一点:
SELECT COUNT(*):
SELECT COUNT(*) 真的那么糟糕吗?
验证记录存在的正确方法是什么?
【问题讨论】:
标签: sql optimization query-optimization
最好使用以下任何一种:
-- Method 1.
SELECT 1
FROM table_name
WHERE unique_key = value;
-- Method 2.
SELECT COUNT(1)
FROM table_name
WHERE unique_key = value;
第一个选项应该没有结果或一个结果,第二个计数应该为零或一个。
您使用的文档有多长时间了?尽管您已经阅读了很好的建议,但最近 RDBMS 中的大多数查询优化器都优化了SELECT COUNT(*),因此尽管理论上(和旧数据库)存在差异,但您不应该注意到实践中的任何差异。
【讨论】:
我宁愿不使用 Count 函数:
IF [NOT] EXISTS ( SELECT 1 FROM MyTable WHERE ... )
<do smth>
例如,如果您想在将用户插入数据库之前检查用户是否存在,则查询可能如下所示:
IF NOT EXISTS ( SELECT 1 FROM Users WHERE FirstName = 'John' AND LastName = 'Smith' )
BEGIN
INSERT INTO Users (FirstName, LastName) VALUES ('John', 'Smith')
END
【讨论】:
你可以使用:
SELECT 1 FROM MyTable WHERE <MyCondition>
如果没有符合条件的记录,则结果记录集为空。
【讨论】:
其他答案都很好,但添加LIMIT 1(或the equivalent,以防止检查不必要的行。
【讨论】:
SELECT COUNT(1) FROM MyTable WHERE ...
将遍历所有记录。这就是它不能用于记录存在的原因。
我会用
SELECT TOP 1 * FROM MyTable WHERE ...
找到1条记录后,终止循环。
【讨论】:
SELECT TOP 1,它会在找到一个之后实际终止还是继续找到所有能够说哪个是TOP?
IF EXISTS (SELECT TOP 1 1 FROM ... WHERE ..)
你可以使用:
SELECT 1 FROM MyTable WHERE... LIMIT 1
使用select 1 防止检查不必要的字段。
使用LIMIT 1 防止检查不必要的行。
【讨论】:
你可以使用:
SELECT COUNT(1) FROM MyTable WHERE ...
或
WHERE [NOT] EXISTS
( SELECT 1 FROM MyTable WHERE ... )
这将比SELECT * 更有效,因为您只需为每一行而不是所有字段选择值 1。
COUNT(*) 和 COUNT(column name) 之间也有细微的差别:
COUNT(*) 将计算所有行,包括空值COUNT(column name) 将只计算列名的非 null 出现次数
【讨论】:
count(1) 和 count(*) 之间的性能差异只会在最脑残的 DBMS 中有所不同。
count(*) 和count(1) 之间没有真正的区别。对于其他 DBMS'是否是这样,我不能说。
其他选项:
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [MyTable] AS [MyRecord])
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END
【讨论】:
CAST(1 AS BIT) 的目的是什么?为什么我不能只写THEN 1 ELSE 0?
我是这样用的:
IF (EXISTS (SELECT TOP 1 FROM Users WHERE FirstName = 'John'), 1, 0) AS DoesJohnExist
【讨论】: