Jim*_*rbs 7 c# sql sql-server performance user-defined-functions
我从我的C#ASP.Net应用程序调用SQL函数(UDF).我调用的函数需要一个"uniqueidentifier"类型的参数.
如果我在SqlCommand的CommandText中进行调用并传递"null",结果会在大约3秒内返回...
SqlCommand Command = new SqlCommand();
Command.Connection = (SqlConnection)(DbDataModifier.CreateConnection());
Command.CommandText = "select * from GetLocalFirmLoginsSummary(null) order by Date asc"
Command.CommandType = CommandType.Text;
Command.Connection.Open();
SqlDataReader Reader = Command.ExecuteReader(); // takes 3 seconds
Run Code Online (Sandbox Code Playgroud)
但是,如果我进行调用并将DBNull.Value作为SqlParameter传递,则结果需要60秒才能返回...
SqlCommand Command = new SqlCommand();
Command.Connection = (SqlConnection)(DbDataModifier.CreateConnection());
Command.CommandText = "select * from GetLocalFirmLoginsSummary(@CustomerGroupID) order by Date asc"
Command.CommandType = CommandType.Text;
SqlParameter Param = new SqlParameter();
Param.ParameterName = "@CustomerGroupID";
Param.SqlDbType = SqlDbType.UniqueIdentifier;
Param.Direction = ParameterDirection.Input;
Param.IsNullable = true;
Param.Value = DBNull.Value;
Command.Parameters.Add(Param);
Command.Connection.Open();
SqlDataReader Reader = Command.ExecuteReader(); // takes over 60 seconds
Run Code Online (Sandbox Code Playgroud)
如果我在SQL Management Studio中运行相同的查询,则大约需要3秒,即使将null作为参数传递...
declare @CustomerGroupID uniqueidentifier
set @CustomerGroupID = null
select * from GetLocalFirmLoginsSummary(@CustomerGroupID)
Run Code Online (Sandbox Code Playgroud)
我正在调用的函数定义为:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetLocalFirmLoginsSummary]
(
@CustomerGroupID uniqueidentifier
)
RETURNS TABLE
AS
RETURN
(
SELECT CustomerGroupID, CustomerGroupName, USR, DATEADD(MONTH, DATEDIFF(MONTH, 0, createdDate), 0) AS Date, COUNT(*) AS Quantity
FROM dbo.GetLocalFirmLogins(@CustomerGroupID) AS Logins
GROUP BY USR, CustomerGroupID, CustomerGroupName, DATEADD(MONTH, DATEDIFF(MONTH, 0, createdDate), 0)
)
Run Code Online (Sandbox Code Playgroud)
...
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetLocalFirmLogins]
(
@CustomerGroupID uniqueidentifier
)
RETURNS TABLE
AS
RETURN
(
SELECT vw_CustomerGroupAccountDetails.CustomerGroupID, vw_CustomerGroupAccountDetails.CustomerGroupName, Organisations.USR, Organisations.town AS FirmTown,
Users.id AS ID, Users.userName, Users.password, Users.isPartner, Users.isFeeEarner, Users.nlisUserName, Users.nlisPassword, Users.email, Users.lastLoginDate, Users.createdDate
FROM vw_CustomerGroupAccountDetails RIGHT OUTER JOIN
Organisations ON vw_CustomerGroupAccountDetails.AccountID = CAST(Organisations.id AS nvarchar(50)) RIGHT OUTER JOIN
Users ON Organisations.clientId = Users.uploadedBy
WHERE (Users.canLogin = 1) AND (Users.isDeleted = 0) AND (NOT (Organisations.USR IS NULL)) AND
((vw_CustomerGroupAccountDetails.CustomerGroupID = @CustomerGroupID) OR (@CustomerGroupID IS NULL))
)
Run Code Online (Sandbox Code Playgroud)
那么当我使用SqlCommand的SqlParame从C#调用SQL函数时,是什么原因导致它花费的时间更长?
我正在使用SQL Server 2000.
我到处搜索并以我能想到的各种方式搜索,但找不到其他人有同样的问题.
吉姆,你能发布 dbo.GetLocalFirmLogins 的来源吗?
正如马丁所说,这可能是参数嗅探。如果是这样,代码中的查询提示可能是“通过手术”解决此问题的最佳方法,其中寻找 @CustomerGroupID 。
将 OPTION (LOOP JOIN) 添加到 dbo.GetLocalFirmLogins 中的查询可以在此处修复。
我想我也可以解释为什么 SSMS 没有看到这个问题,而 C# 却看到了。这部分查询:
(CustomerGroupID = @CustomerGroupID) OR (@CustomerGroupID IS NULL)
Run Code Online (Sandbox Code Playgroud)
根据您所来自的连接的 ANSI NULL 设置,可能有两个不同的计划。ANSI NULL 及其效果描述如下:
您可以通过检索此查询的结果来查看连接的 ANSI 设置:
SSMS 可能具有与您 C# 编码不同的 NULL 设置,并导致对查询进行不同的评估。
| 归档时间: |
|
| 查看次数: |
4075 次 |
| 最近记录: |