我想编写一个简单返回1或0的查询,具体取决于是否有结果。
我正在考虑使用这个
IF EXISTS(
select * from myTable
where id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
)
SELECT 1
ELSE
SELECT 0
这是一般的前提。
最终结果实际上是一个更复杂的查询,采用一对多参数,并使用sp_executesql构建和执行字符串
我的问题是让'计数'返回376986并需要4秒钟来计算。使用IF EXISTS会在找到满足条件的1行后立即停止。
我决定使用IF EXISTS或只是查询@@ ROWCOUNT并查看它是否大于零。
我确实尝试了一些测试,并且几乎都以相同的速度运行,但是在2年的时间里,有很多数据可能使用IF EXISTS会不会有性能提升?
由于
答案 0 :(得分:11)
你有id和日期的索引吗?
也许你只想要:
select top 1 1 from myTable where id=7 and rowInsertDate > '01/01/2009'
注意:如果数据存在,则返回1,否则返回。
另一个编辑。如果没有数据,则不会返回值为null的行,而是不返回任何行。在更具象征意义上更像是无效。
答案 1 :(得分:10)
这是我在项目中获得的最快速度:
SELECT CASE WHEN EXISTS (
select top 1 1
from myTable
where id=7
and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
) THEN 1 ELSE 0 END AS AnyData
答案 2 :(得分:7)
如果EXISTS应该更有效率,因为它被优化为在找到第一行后立即停止。这就是我总是会做这种检查,而不是使用COUNT()。
为了进行性能比较,只需确保通过在每次测试之前清除数据和执行计划缓存(仅限非生产数据库服务器)来公平地进行测试:
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
答案 3 :(得分:3)
我会这样写:
IF EXISTS(
SELECT 0 FROM myTable
WHERE id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE()
)
SELECT 1
ELSE
SELECT 0
这样你不会返回任何数据只是检查条件。我发现这个查询结构超级快。
答案 4 :(得分:2)
如果您不需要376986行,只想知道是否存在某些内容,那么IF EXISTS会更有意义。 另外,另一个有用的方法是请求索引列(主键)而不是*,因为您不关心实际数据。
答案 5 :(得分:1)
最终结果实际上是一个 更复杂的查询,拿一个 许多参数和字符串构建 使用sp_executesql
执行并执行
我认为你至少需要完整的FROM,JOIN和WHERE语法,否则你的实际查询可能会找不到(例如通过添加一个不在原始IF EXISTS查询中的INNER JOIN,结果证明不满意)。
如果您遇到这种麻烦,您可能希望将PK转换为某种“批次ID保持表”,这样您就可以参考查询的第二个“演示”部分的PK。
如果您获得376,986个结果,您打算做什么?如果您要在屏幕上向用户显示这些内容,并进行某种分页,那么将结果放在“批次ID保持表”中可能有助于此(尽管显然,对于udnerlying数据的任何添加/删除等)会破坏分页显示。)
或者,如果你打算使用分页,只需使用TOP / LIMIT / SET ROWCOUNT将结果限制为第一页完整(确保你有一个ORDER BY,这样序列是可重复的),然后整理出什么当用户按下NEXT-PAGE按钮时(我们通过包含显示的最后一条记录的PK的NEXT-PAGE按钮按顺序处理它,以便下一页可以从那时起恢复)
查询优化器会根据SELECT列表执行不同的操作 - 因此询问“IF EXISTS”后跟“SELECT Col1,COl2,... FROM ...”实际上可能意味着您运行完整的查询两次,不同的是,使用不同的缓存数据和查询计划,总体而言,这可能会对您的服务器造成更大的压力,并导致用户等待更长时间,而不仅仅是设置第一页/ 100行等。
SQL Server将缓存sp_ExecuteSQL的查询计划,但请确保参数化查询以便在可能的情况下重新启动缓存计划
答案 6 :(得分:0)
首先,您应该尝试假设一个数据库包含您认为您(或您的继任者)可能需要在两年内处理的数据。那么你的测试将会更有效率。
如果EXISTS()速度更快,因为数据库引擎只需找到符合条件的第一条匹配记录。当然,使用适当的索引会更快。
另一个提示,不要使用*,因为您实际上不需要检索列。
IF EXISTS(select 1 from myTable where id=7 and rowInsertDate BETWEEN '01/01/2009' AND GETDATE())
...应该(从我读过的内容)工作得更快。
答案 7 :(得分:0)
我认为Alex Bagnolini的回答是正确的。系统不会让我评论他的回答(新的acct)。我做的唯一修改是将第二个1更改为id。
有时减少项目部分中的列表(即列列表)允许db引擎仅命中索引,而不是表,因此更快。当然,这取决于您的数据库引擎和索引结构/大小。 (所有rowInsertDate日期应为< getDate(),因此您可以跳过该比较)
EXISTS时选择案例( 选择前1个id 来自myTable 其中id = 7 和rowInsertDate> '01 / 01 / 2009' )然后1 ELSE 0结束为AnyData
答案 8 :(得分:0)