是"where(ParamID = @ParamID)OR(@ParamID = -1)"sql选择的一个好习惯

Geo*_*ros 10 sql sql-server performance filter database-performance

我曾经写过像sql一样的语句

select * from teacher where (TeacherID = @TeacherID) OR (@TeacherID = -1)
Run Code Online (Sandbox Code Playgroud)

阅读更多

并传递@TeacherID值= -1以选择所有教师

现在我担心你能告诉我的表现是一个好的练习还是坏的一个?

非常感谢

Not*_*tMe 6

我们在存储过程中以非常有限的方式使用它.

问题是数据库引擎无法为它保留良好的查询计划.处理大量数据时,可能会对性能产生严重的负面影响.

但是,对于较小的数据集(我说少于1000条记录,但这是猜测)应该没问题.你必须在你的特定环境中进行测试.

如果它在存储过程中,您可能希望包含类似WITH RECOMPILE选项的内容,以便在每次执行时重新生成计划.这会(稍微)增加每次运行的时间,但是多次运行实际上可以减少平均执行时间.此外,这允许数据库检查实际查询并"短路"每次呼叫不必要的部分.

如果你是直接创建你的SQL并通过它,那么我建议你使构建你的sql的部分更聪明一点,这样它只包含你实际需要的where子句的一部分.


您可能考虑的另一个路径是使用UNION ALL查询而不是可选参数.例如:

SELECT * FROM Teacher WHERE (TeacherId = @TeacherID)
UNION ALL
SELECT * FROM Teacher WHERE (@TeacherId = -1)
Run Code Online (Sandbox Code Playgroud)

这实际上完成了同样的事情; 但是,查询计划是可缓存的.我们也在一些地方使用过这种方法,并且比使用WITH RECOMPILE看到了性能提升.我们不是在任何地方都这样做,因为我们的一些查询非常复杂,而且我更倾向于性能损失而不是使它们进一步复杂化.

但最终,您需要进行大量测试.


这里有第二部分你应该重新考虑. SELECT *. 总是命名您想要返回的列并确保您返回实际需要的列,这总是更可取的.跨网络边界移动数据非常昂贵,只需准确指定您想要的内容,通常可以获得相当大的性能提升.此外,如果您需要的是非常有限的,您有时可以覆盖索引,以便数据库引擎甚至不必触及基础表来获取所需的数据.

  • @hvd:极少数人会使用负数作为Id.如果您处于这种情况,那么您应该只传递null并测试它而不是使用-1 (2认同)

Mar*_*ith 6

如果TeacherID被索引,你逝去的值以外-1TeacherID搜索一个特定教师的详细信息,则此查询最终会做一个全表扫描,而不是寻求进入指数的潜在的更有效的选择要检索的细节特定老师......

...除非您使用SQL 2008 SP1 CU5及更高版本并使用OPTION (RECOMPILE)提示.有关该主题的权威文章,请参阅T-SQL中的动态搜索条件.