none
SQL Stored procedure's Performance question about sp_executesql RRS feed

  • 問題

  • 你好

    我有一些關於 sql performance 的問題
    我想知道大家在sql stored procedure 入面多唔多用 EXECUTE sp_executesql 這個function?
    我有位同事說用 如果我們 create 一個variable as string
    store 要execute 的 sql query 在這個string 入面
    之後用 EXECUTE sp_executesql
    會比就咁寫這個query 的performance 會好 一點

    但我常常都會覺得 stored procedure 是因為我們每次execute 時都會有記錄
    所以大概知道 個process 會做什麼
    如果我們用 EXECUTE sp_executesql 我便會覺得 當 sp_executesql run 的時候
    每次都要再 process 過這個query 的 logic 了
    所以不知道用不用他的用法好

    e.g.

    DECLARE @NewSQLString nvarchar(500)
    set @NewSQLString = 'SELECT * FROM TBL1 INNER JOIN TBL2 ON TBL1.ID=TBL2.ID WHERE '
    set @NewSQLString = @NewSQLString + 'TBL1.PRODUCE=' + '''' +@Produce +''''

    EXECUTE sp_executesql @NewSQLString

    VS

    SELECT * FROM TBL1 INNER JOIN TBL2 ON TBL1.ID=TBL2.ID
    WHERE TBL1.PRODUCE=@Produce


    希望大家可以比一些 advise 同idea我
    那個performance 會好一點

    謝謝大家
    2008年10月20日 上午 09:52

解答

  •  

    In your case, I would prefer using sp_executesql for your query if your second query is an ad-hoc query.  It is because SQL Server will store and re-use the execution plan of the command used in sp_executesql.  As far as I know, execution plan may not be re-used for ad-hoc query (please correct me if I am wrong).

     

    For more information about performance tuning in SQL Server, you can refer to the following:

    http://msdn.microsoft.com/en-us/library/ms998577.aspx

     

    2008年10月20日 下午 01:32
  • For me, sp_executesql is usually used inside a stored procedure for dynamic SQL statements, by which the exact list of columns, tables, or WHERE / GROUP BY / HAVING clauses can only be known during run time.

     

    From your post, I expect that you are trying to compare the performance differences between the different statements that are to be placed inside your stored procedures (separately), and thus, your enquiry relates to caching (and recompilation) of query plan in SQL Server.

     

    Before executing a stored procedure, SQL Server tries to obtain a query plan of that stored procedure from the plan cache (there are exceptions). If a suitable query plan cannot be found from the plan cache, SQL Server compiles a query plan for your stored procedure. This is the compilation cost before executing the query plan.

     

    *** *** *** *** *** ***

    *** dbo.usp_ListWorkOrder01 *** For your first statement starting with 'DECLARE...'

    *** *** *** *** *** ***

    Please note that I have modified your statement such that it takes a parameter, instead of assigning TBL1.PRODUCE to a constant (@Produce).

     

    CREATE procedure [dbo].[usp_ListWorkOrder01] @sProduce int = 0
    as 

       DECLARE @MySQL nvarchar(500)

       DECLARE @MyParmDefinition nvarchar(500)
       set @MySQL = 'SELECT * FROM TBL1 INNER JOIN TBL2 ON TBL1.ID=TBL2.ID

          + ' WHERE TBL1.PRODUCE= @MyProduce'

       EXECUTE sp_executesql @MySQL, @MyParmDefinition, @MyProduce = @sProduce

    GO

     

    SQL Server creates execution plans for the following.

    (1) Stored procedure [dbo].[usp_ListWorkOrder01]

    (2) Prepared statement 'SELECT * FROM TBL1 INNER JOIN TBL2 ON TBL1.ID=TBL2.ID WHERE TBL1.PRODUCE= @MyProduce

     

    *** *** *** *** *** ***

    *** dbo.usp_ListWorkOrder02 *** For your second statement...

    *** *** *** *** *** ***

    CREATE procedure [dbo].[usp_ListWorkOrder02] @sProduce int = 0

    as

       SELECT * FROM TBL1 INNER JOIN TBL2 ON TBL1.ID=TBL2.ID
          WHERE TBL1.PRODUCE = @sProduce

    GO

     

    SQL Server creates execution plan for the following.

    (1) Stored procedure [dbo.][usp_ListWorkOrder02]

     

    *** *** *** *** *** ***

    In any case, SQL Server requiers query plans for execution.

     

    In dbo.usp_ListWorkOrder02, the whole query plan is retrieved (or compiled) once, and then executed.

     

    In dbo.usp_ListWorkOrder01, additional execution overhead is added by calling the stored procedure sp_executesql, which includes getting (or compiling) the query plan of the prepared statement (SELECT), and the related execution context for executing the query plan.

     

    === For more information ===

    ~ Parameters and execution plan reuse

    http://msdn.microsoft.com/en-us/library/ms175580.aspx

     

    ~ sys.syscacheobjects (Transact-SQL)

    http://msdn.microsoft.com/en-us/library/ms187815.aspx

     

    2008年10月21日 上午 10:38
  • Whether we should use static or dynamic SQL statements does NOT relate to an IF statement.

    When choosing between static / dynamic SQL statements, you are suggested to use static SQL statements (usp_ListWorkOrder02) for most of the cases. Dynamic SQL statements are usually used when static SQL statements cannot fulfill your needs. Thus, use dynamic SQL statements (usp_ListWorkOrder01) only when you do NOT know the table names or the column names for a particular statement, or when the selection conditions (WHERE) is too complicated to be handled in a static way. (while there are still alternatives / workarounds for not using dynamic SQL statements.)

     

     

     

    When comparing the performance, usp_ListWorkOrder02 (the static one) is better as it involves less query plan lookup (or compilation).

     

    For usp_ListWorkOrder01 (stored proc with dynamic SQL statement), it involves 2 query plans.

    SQL Server compiles a query plan for the stored procedure, and another query plan for the parameterized statement called by sp_executesql.

     

    For usp_ListWorkOrder02 (stored proc with static SQL statement), it involves 1 query plan.

    SQL Server compiles a query plan for the stored procedure.

     

    All of these query plans are stored in the plan cache and can be reused.

     

     

     

    Lastly, quoting from your first post.

    <--- Quote starts --->

    我有位同事說用 如果我們 create 一個variable as string
    store 要execute 的 sql query 在這個string 入面
    之後用 EXECUTE sp_executesql
    會比就咁寫這個query 的performance 會好 一點
    <--- Quote ends --->

     

    What exactly does your colleague mean by [ 會比就咁寫這個query 的performance 會好 一點 ]?

    or, what is being compared against using sp_executesql?

    Can your colleague point you to any references?
    2008年10月21日 下午 09:49

所有回覆

  •  

    In your case, I would prefer using sp_executesql for your query if your second query is an ad-hoc query.  It is because SQL Server will store and re-use the execution plan of the command used in sp_executesql.  As far as I know, execution plan may not be re-used for ad-hoc query (please correct me if I am wrong).

     

    For more information about performance tuning in SQL Server, you can refer to the following:

    http://msdn.microsoft.com/en-us/library/ms998577.aspx

     

    2008年10月20日 下午 01:32
  • For me, sp_executesql is usually used inside a stored procedure for dynamic SQL statements, by which the exact list of columns, tables, or WHERE / GROUP BY / HAVING clauses can only be known during run time.

     

    From your post, I expect that you are trying to compare the performance differences between the different statements that are to be placed inside your stored procedures (separately), and thus, your enquiry relates to caching (and recompilation) of query plan in SQL Server.

     

    Before executing a stored procedure, SQL Server tries to obtain a query plan of that stored procedure from the plan cache (there are exceptions). If a suitable query plan cannot be found from the plan cache, SQL Server compiles a query plan for your stored procedure. This is the compilation cost before executing the query plan.

     

    *** *** *** *** *** ***

    *** dbo.usp_ListWorkOrder01 *** For your first statement starting with 'DECLARE...'

    *** *** *** *** *** ***

    Please note that I have modified your statement such that it takes a parameter, instead of assigning TBL1.PRODUCE to a constant (@Produce).

     

    CREATE procedure [dbo].[usp_ListWorkOrder01] @sProduce int = 0
    as 

       DECLARE @MySQL nvarchar(500)

       DECLARE @MyParmDefinition nvarchar(500)
       set @MySQL = 'SELECT * FROM TBL1 INNER JOIN TBL2 ON TBL1.ID=TBL2.ID

          + ' WHERE TBL1.PRODUCE= @MyProduce'

       EXECUTE sp_executesql @MySQL, @MyParmDefinition, @MyProduce = @sProduce

    GO

     

    SQL Server creates execution plans for the following.

    (1) Stored procedure [dbo].[usp_ListWorkOrder01]

    (2) Prepared statement 'SELECT * FROM TBL1 INNER JOIN TBL2 ON TBL1.ID=TBL2.ID WHERE TBL1.PRODUCE= @MyProduce

     

    *** *** *** *** *** ***

    *** dbo.usp_ListWorkOrder02 *** For your second statement...

    *** *** *** *** *** ***

    CREATE procedure [dbo].[usp_ListWorkOrder02] @sProduce int = 0

    as

       SELECT * FROM TBL1 INNER JOIN TBL2 ON TBL1.ID=TBL2.ID
          WHERE TBL1.PRODUCE = @sProduce

    GO

     

    SQL Server creates execution plan for the following.

    (1) Stored procedure [dbo.][usp_ListWorkOrder02]

     

    *** *** *** *** *** ***

    In any case, SQL Server requiers query plans for execution.

     

    In dbo.usp_ListWorkOrder02, the whole query plan is retrieved (or compiled) once, and then executed.

     

    In dbo.usp_ListWorkOrder01, additional execution overhead is added by calling the stored procedure sp_executesql, which includes getting (or compiling) the query plan of the prepared statement (SELECT), and the related execution context for executing the query plan.

     

    === For more information ===

    ~ Parameters and execution plan reuse

    http://msdn.microsoft.com/en-us/library/ms175580.aspx

     

    ~ sys.syscacheobjects (Transact-SQL)

    http://msdn.microsoft.com/en-us/library/ms187815.aspx

     

    2008年10月21日 上午 10:38
  • Hi Raymond and Martin

    Thanks very much for your information.
    Yeah, I am trying to compare the performance between these 2 stored procedures.

    To ensure I did not mis-understood
    To Martin:
     "For me, sp_executesql is usually used inside a stored procedure for dynamic SQL statements, by which the exact list of columns, tables, or WHERE / GROUP BY / HAVING clauses can only be known during run time. "

    Do you mean, for situation like, you have to use IF Statement on the Stored procedure, you would suggest to use sp_executesql? or I mis-understood you about the meaning of dynamic SQL statement. (sorry, I am a bit stupid about understanding things)

    For the second SQL statement, it would perform better than using sp_executesql?, because SQL Server can re-use the Execute plan?

    Please forgive me if I mis-understood you.


    Thanks very much for your help.

    Chi

    2008年10月21日 上午 11:06
  • Whether we should use static or dynamic SQL statements does NOT relate to an IF statement.

    When choosing between static / dynamic SQL statements, you are suggested to use static SQL statements (usp_ListWorkOrder02) for most of the cases. Dynamic SQL statements are usually used when static SQL statements cannot fulfill your needs. Thus, use dynamic SQL statements (usp_ListWorkOrder01) only when you do NOT know the table names or the column names for a particular statement, or when the selection conditions (WHERE) is too complicated to be handled in a static way. (while there are still alternatives / workarounds for not using dynamic SQL statements.)

     

     

     

    When comparing the performance, usp_ListWorkOrder02 (the static one) is better as it involves less query plan lookup (or compilation).

     

    For usp_ListWorkOrder01 (stored proc with dynamic SQL statement), it involves 2 query plans.

    SQL Server compiles a query plan for the stored procedure, and another query plan for the parameterized statement called by sp_executesql.

     

    For usp_ListWorkOrder02 (stored proc with static SQL statement), it involves 1 query plan.

    SQL Server compiles a query plan for the stored procedure.

     

    All of these query plans are stored in the plan cache and can be reused.

     

     

     

    Lastly, quoting from your first post.

    <--- Quote starts --->

    我有位同事說用 如果我們 create 一個variable as string
    store 要execute 的 sql query 在這個string 入面
    之後用 EXECUTE sp_executesql
    會比就咁寫這個query 的performance 會好 一點
    <--- Quote ends --->

     

    What exactly does your colleague mean by [ 會比就咁寫這個query 的performance 會好 一點 ]?

    or, what is being compared against using sp_executesql?

    Can your colleague point you to any references?
    2008年10月21日 下午 09:49
  • Hi Martin,

    Thanks very much for your explanation again. I understood more now. My colleague did not point me to any reference, I may ask him again.

    Thanks a lot.
    2008年10月22日 上午 07:31