简体   繁体   中英

C# ADO.net query runs slow

I have a query that .net builds and executes via ADO to Sql Server 2012. If ADO executes the query it times out waiting for the database to return but if I copy and past it into SQL Management studio and execute it against the same database it returns in less then a second.

I found that wrapping the query that ADO generates in ' storing it in a SQL variable and using SP_EXECUTESQL makes it run nice and fast. Why would there be a difference? I have not changed the query in any way.

Here is one of the queries it builds and executes (I left out all the code that dynamically builds the string that CommandText gets set to).

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();
}

This kind of behaviour is usually caused by parameter sniffing problems. You can try with option recompile or optimize for unknown .

Option recompile

....
WHERE broadcastEntity.AgencyID = @agencyID
            AND keys.AgencyEntityBroadcastID IS NULL
OPTION (RECOMPILE)

Optimize for unknown

.....
WHERE broadcastEntity.AgencyID = @agencyID
      AND keys.AgencyEntityBroadcastID IS NULL
OPTION (OPTIMIZE FOR (@agencyID UNKNOWN, @broadcastEntityMappingID UNKNOWN))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM