在sql server 2005存储过程中使用函数调用?
在存储过程的 where 子句中使用函数调用会降低 sql server 2005 的性能?
SELECT * FROM Member M
WHERE LOWER(dbo.GetLookupDetailTitle(M.RoleId,'MemberRole')) != 'administrator'
AND LOWER(dbo.GetLookupDetailTitle(M.RoleId,'MemberRole')) != 'moderator'
在此查询中, GetLookupDetailTitle 是用户定义的函数,而 LOWER() 是内置函数,我正在询问这两个函数。
Use of function calls in where clause of stored procedure slows down performance in sql server 2005?
SELECT * FROM Member M
WHERE LOWER(dbo.GetLookupDetailTitle(M.RoleId,'MemberRole')) != 'administrator'
AND LOWER(dbo.GetLookupDetailTitle(M.RoleId,'MemberRole')) != 'moderator'
In this query GetLookupDetailTitle is a user defined function and LOWER() is built in function i am asking about both.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的。
这两种做法都是应尽可能避免的。
将几乎任何函数应用于列可以使表达式 unsargable 这意味着无法使用索引,即使该列没有索引,它也会使计划的其余部分的基数估计不正确。
此外,您的 dbo.GetLookupDetailTitle 标量函数看起来像是进行数据访问,这应该内联到查询中。
查询优化器不会从标量 UDF 内联逻辑,并且您的查询将为源数据中的每一行执行此查找,这将有效地强制执行嵌套循环连接,无论其适用性如何。
此外,由于有 2 个函数调用,这实际上每行会发生两次。您可能应该重写为类似的内容,
不要试图将文字值
1,2
替换为具有更具描述性名称的变量,因为这也可能会扰乱基数估计。Yes.
Both of these are practices to be avoided where possible.
Applying almost any function to a column makes the expression unsargable which means an index cannot be used and even if the column is not indexed it makes cardinality estimates incorrect for the rest of the plan.
Additionally your
dbo.GetLookupDetailTitle
scalar function looks like it does data access and this should be inlined into the query.The query optimiser does not inline logic from scalar UDFs and your query will be performing this lookup for each row in your source data, which will effectively enforce a nested loops join irrespective of its suitability.
Additionally this will actually happen twice per row because of the 2 function invocations. You should probably rewrite as something like
Don't be tempted to replace the literal values
1,2
with variables with more descriptive names as this too can mess up cardinality estimates.在
WHERE
子句中使用函数强制进行表扫描。无法使用索引,因为引擎在运行该函数之前无法知道结果是什么表中的每一行。
Using a function in a
WHERE
clause forces a table scan.There's no way to use an index since the engine can't know what the result will be until it runs the function on every row in the table.
来避免使用用户定义函数和内置函数
为管理员和主持人角色定义“魔术”值并将 Member.RoleId 与这些标量进行比较
在 MemberRole 表上定义 IsAdministrator 和 IsModerator 标志,并与 Member 联接以过滤这些标志
You can avoid both the user-defined function and the built-in by
defining "magic" values for administrator and moderator roles and compare Member.RoleId against these scalars
defining IsAdministrator and IsModerator flags on a MemberRole table and join with Member to filter on those flags