Why does a query slow down drastically if in the WHERE clause a constant is replaced by a parameter (having the same value)?

前端 未结 4 1930
清歌不尽
清歌不尽 2021-01-02 03:19

I have a recursive query which executes very fast if the WHERE clause contains a constant but becomes very slow if I replace the constant with a parameter havin

相关标签:
4条回答
  • 2021-01-02 03:49

    As Martin suggested in a comment under the question, the problem is that SQL server does not push down properly the predicate from the WHERE clause - see the link in his comment.

    I ended up with creating a user defined table-valued function and use it with the CROSS APPLY operator for creating the view.

    Let's see the solution itself.

    User Defined Table-valued Function

    CREATE FUNCTION [dbo].[TestFunction] (@Id INT)
    RETURNS TABLE 
    AS
    RETURN 
    (
        WITH
        Hierarchy (Id,  ParentId, Data, Depth)
        AS(
        SELECT Id, ParentId, NULL AS Data, 0 AS Depth FROM Test Where Id = @Id
        UNION ALL
        SELECT h.Id, t.ParentId, COALESCE(h.Data, t.Data), Depth + 1 AS Depth
            FROM Hierarchy h
                INNER JOIN Test t ON t.Id = h.ParentId
        )
        SELECT * FROM Hierarchy
    )
    

    View

    CREATE VIEW [dbo].[TestView]
    AS
    SELECT t.Id, t.ParentId, f.Data, f.Depth
    FROM
        Test AS t
        CROSS APPLY TestFunction(Id) as f
    

    Query with constant

    SELECT * FROM TestView WHERE Id = 69
    

    Query with parameter

    DECLARE @Id INT
    SELECT @Id = 69
    SELECT * FROM TestView WHERE Id = @Id
    

    The query with the parmater executes basically as fast as the query with the constant.

    Thank You Martin and for the others as well!

    0 讨论(0)
  • 2021-01-02 03:54

    For your second Query try using the OPTIMIZE FOR or OPTION(RECOMPILE) query hint to see if that forces it to recomplile based on the provided parameter value.

    0 讨论(0)
  • 2021-01-02 03:55

    You should use a plan guide to freeze the plan you want.

    0 讨论(0)
  • 2021-01-02 04:03

    This could be the worse suggestion ever, but have you considered creating a sproc to create your query as a string and execute it using sp_executesql?

    I know nothing about the caching behaviour of SQL executed by sp_executesql, it was just the first thing to pop into my head.

    0 讨论(0)
提交回复
热议问题