【发布时间】:2023-03-21 08:23:01
【问题描述】:
我正在从我的 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
但是,如果我进行调用并将 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
如果我在 SQL Management Studio 中运行相同的查询,大约需要 3 秒,即使将 null 作为参数传递...
declare @CustomerGroupID uniqueidentifier
set @CustomerGroupID = null
select * from GetLocalFirmLoginsSummary(@CustomerGroupID)
我调用的函数定义为:
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)
)
...
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))
)
那么,当我使用 SqlCommand 的 SqlParameter 从 C# 调用 SQL 函数时,是什么导致它花费了这么长时间?
我使用的是 SQL Server 2000。
我已经到处搜索了所有我能想到的方法,但找不到其他人有同样的问题。
【问题讨论】:
-
当您说 SQL 时,您不是在谈论独立于数据库的Structured Query Language,而是在讨论 Microsoft 数据库产品SQL Server,对吗?
-
很可能是参数嗅探。
-
您是否测试过它是否特定于null?什么是正常值?
-
我怀疑 Martin 说这可能是参数嗅探,尝试将参数变量分配给局部变量并在查询中使用局部变量,这可能有助于提高性能。
-
在GetLocalFirmLoginsSummary调用的名为GetLocalFirmLogins的UDF中,过滤“@CustomerGroupID IS NULL”。
标签: c# sql sql-server performance user-defined-functions