C#ADO.net查询运行缓慢
我有一个.net通过ADO到Sql Server 2012构建和执行的查询。如果ADO执行查询,它会在等待数据库返回时超时,但如果我将其复制并通过SQL Management studio并针对同一数据库执行查询,它将在不到一秒钟的时间内返回 我发现,将ADO生成的查询包装在“将其存储在SQL变量中并使用SP_EXECUTESQL”中,可以使其运行良好且快速。为什么会有区别呢?我没有以任何方式更改查询 这里是它构建和执行的查询之一(我省略了动态构建CommandText设置为的字符串的所有代码)C#ADO.net查询运行缓慢,c#,ado.net,sql-server-2012,C#,Ado.net,Sql Server 2012,我有一个.net通过ADO到Sql Server 2012构建和执行的查询。如果ADO执行查询,它会在等待数据库返回时超时,但如果我将其复制并通过SQL Management studio并针对同一数据库执行查询,它将在不到一秒钟的时间内返回 我发现,将ADO生成的查询包装在“将其存储在SQL变量中并使用SP_EXECUTESQL”中,可以使其运行良好且快速。为什么会有区别呢?我没有以任何方式更改查询 这里是它构建和执行的查询之一(我省略了动态构建CommandText设置为的字符串的所有代码)
这种行为通常是由问题引起的。您可以尝试使用“重新编译”或“针对未知对象进行优化”选项 选项重新编译 为未知优化
注意不要对
varchar
列使用nvarchar
参数,因为这会导致隐式强制转换,请注意,我们的应用程序是国际性的,因此我们对所有列都使用nvarchar。在using语句生成字符串之前,我必须创建一个存储过程,以完成大量.NET代码行的工作。字符串是动态构建的,因此每次执行它时,结构都是一致的。插入的数量及其为临时表选择的表都是动态的。将两个实际的查询计划作为XML发布并比较它们(禁用超时以获得较慢的计划)。它们可能会在慢速版本中显示转换警告。不需要这样做。特设SQL能够实现相同级别的性能。只需使用SQL事件探查器捕获计划。有一个XML Showplan事件。或者,捕获查询并在SSMS中重新执行它们。
using(SqlConnection conn = ConnectionStringHelper.GetOpenConnection)
using(SqlCommand cmd = conn.CreateCommand)
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("agencyID", broadcastAgencyID);
cmd.Parameters.AddWithValue("tableName", mapping.TableName);
cmd.Parameters.AddWithValue("schemaName", mapping.SchemaName);
cmd.Parameters.AddWithValue("broadcastEntityMappingID", mapping.BroadcastEntityMappingID);
cmd.CommandText = @"SET NOCOUNT ON;
DECLARE @currentAgencyID NVARCHAR(MAX)
DECLARE @currentFacilityID NVARCHAR(MAX)
DECLARE @currentAgencyEntityBroadcastID INT
SELECT broadcastEntity.AgencyID, broadcastEntity.FacilityID
INTO #missingBroadcasts
FROM [Resource].[AgencyFacility] broadcastEntity
LEFT JOIN(
SELECT keys.AgencyID, keys.FacilityID
, record.BroadcastAgencyID
, record.AgencyEntityBroadcastID
FROM [Propagation].[AgencyEntityBroadcast] record
INNER JOIN (
SELECT AgencyEntityBroadcastID
,[AgencyID], [FacilityID]
FROM (
SELECT AgencyEntityBroadcastID
,ColumnName AS [PropagationColumnName]
,ColumnValue AS [PropagationColumnValue]
FROM Propagation.AgencyEntityBroadcastKeys
) Keys
PIVOT(MAX(PropagationColumnValue) FOR PropagationColumnName IN (
[AgencyID], [FacilityID]
)) pivoted
) keys ON keys.AgencyEntityBroadcastID = record.AgencyEntityBroadcastID
WHERE record.BroadcastAgencyID = @agencyID
AND record.BroadcastEntityMappingID = @broadcastEntityMappingID
) keys ON keys.BroadcastAgencyID = broadcastEntity.AgencyID
AND keys.AgencyID = broadcastEntity.AgencyID
AND keys.FacilityID = broadcastEntity.FacilityID
WHERE broadcastEntity.AgencyID = @agencyID
AND keys.AgencyEntityBroadcastID IS NULL
DECLARE entity_cursor CURSOR FOR
SELECT * FROM #missingBroadcasts
OPEN entity_cursor
FETCH NEXT FROM entity_cursor
INTO @currentAgencyID, @currentFacilityID
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO Propagation.AgencyEntityBroadcast(
BroadcastAgencyID,
BroadcastEntityMappingID,
BroadcastTypeID,
CreatedOn,
ModifiedOn
)
VALUES(
@agencyID,
@broadcastEntityMappingID,
1,
GETUTCDATE(),
GETUTCDATE()
)
SET @currentAgencyEntityBroadcastID = (SELECT SCOPE_IDENTITY())
INSERT INTO Propagation.AgencyEntityBroadcastKeys(
AgencyEntityBroadcastID,
ColumnName,
ColumnValue
) VALUES (
@currentAgencyEntityBroadcastID,
'AgencyID',
@currentAgencyID
)
INSERT INTO Propagation.AgencyEntityBroadcastKeys(
AgencyEntityBroadcastID,
ColumnName,
ColumnValue
) VALUES (
@currentAgencyEntityBroadcastID,
'FacilityID',
@currentFacilityID
)
FETCH NEXT FROM entity_cursor INTO @currentAgencyID, @currentFacilityID
END
CLOSE entity_cursor
DEALLOCATE entity_cursor
DROP TABLE #missingBroadcasts
SET NOCOUNT OFF;";
cmd.ExecuteNonQuery();
}
....
WHERE broadcastEntity.AgencyID = @agencyID
AND keys.AgencyEntityBroadcastID IS NULL
OPTION (RECOMPILE)
.....
WHERE broadcastEntity.AgencyID = @agencyID
AND keys.AgencyEntityBroadcastID IS NULL
OPTION (OPTIMIZE FOR (@agencyID UNKNOWN, @broadcastEntityMappingID UNKNOWN))