存储过程中准备好的SQL语句是否会提高性能?

存储过程中准备好的SQL语句是否会提高性能?,sql,database,stored-procedures,db2,dynamic-sql,Sql,Database,Stored Procedures,Db2,Dynamic Sql,我知道关于存储过程和准备好的SQL语句已经有很多问题了,但是我想找出一些不同的东西-如果过程中准备好的语句有助于提高存储过程的性能,这意味着使它更好 我有这个问题是因为我在搜索这两种技能的介绍时被告知以下几点 存储过程将在中存储和编译一系列语句 db,这将减少传输和编译的开销 Prepare语句将被编译并缓存在数据库中,以供多个 可减少开销的访问 我对这些“编译”、“存储”和“开销”——有点抽象——感到困惑 我使用prepared语句避免频繁调用时重新解析。 但是,我应该在过程中使用准备好的

我知道关于存储过程和准备好的SQL语句已经有很多问题了,但是我想找出一些不同的东西-如果过程中准备好的语句有助于提高存储过程的性能,这意味着使它更好

我有这个问题是因为我在搜索这两种技能的介绍时被告知以下几点

  • 存储过程将在中存储和编译一系列语句 db,这将减少传输和编译的开销
  • Prepare语句将被编译并缓存在数据库中,以供多个
    可减少开销的访问
我对这些“编译”、“存储”和“开销”——有点抽象——感到困惑

我使用prepared语句避免频繁调用时重新解析。 但是,我应该在过程中使用准备好的语句(缓存和编译)?因为我的过程已经存储并编译在DB中,所以在里面准备一些东西似乎没有意义。(编译什么?)

使用示例代码编辑:

Create or Replace procedure MY_PROCEDURE
Begin
    //totally meaningless here?
    declare sqlStmt varchar(300);
    declare stmt statement;

    set sqlStmt='update MY_TABLE set NY_COLUMN=? where NY_COLUMN=?';
    prepare stmt from sqlStmt;
    execute stmt using 2,1
    execute stmt using 4,3
        ..............
END
上面的方法比下面的方法好吗,因为它只解析语句一次?或者是相同的,因为过程中的语句是预编译的

Create or Replace procedure MY_PROCEDURE
Begin
    update MY_TABLE set NY_COLUMN=2 where NY_COLUMN=1;
    update MY_TABLE set NY_COLUMN=4 where NY_COLUMN=3;
        ..............
END

当您第一次运行存储过程时,数据库引擎将解析该过程并计算出执行该过程时要使用的最佳查询计划-然后它将存储该查询计划,以便每次运行该过程时都不必重新计算它

你可以在管理工作室看到这张照片。如果
创建
更改
相关存储过程,请打开一个新查询并使用:

SET STATISTICS TIME ON
在同一查询窗口中运行存储过程。在结果的messages选项卡中,第一条消息类似于:

SQL Server parse and compile time: 
CPU time = 1038 ms, elapsed time = 1058 ms.
这是开销,再次执行查询,您将看到解析和编译时间现在为0

当您在代码中准备语句时,您可以利用相同的优势。如果查询是
“从@var='+$var
的表中选择*,则每次运行该查询时,SQL Server都必须对其进行分析并计算最佳执行计划。如果使用准备好的语句
SELECT*FROM table WHERE?
,SQL Server将在您第一次运行准备好的语句时计算最佳执行计划,从那时起,它可以将执行计划与存储过程一起重用。如果您正在执行的语句是
'EXEC dbo.myProc@var='+$var
,则SQL Server每次仍必须解析此语句,因此仍应使用准备好的语句

您不需要准备在存储过程中编写的语句,因为它们已经按照上面所示进行了编译——它们本身就是准备好的语句

在使用存储过程和准备好的语句时,您应该注意的一点是参数嗅探

SQL Server计算并存储所使用的第一个变量的最佳执行计划,如果您在第一次运行时碰巧使用某个异常变量执行存储过程,则存储的执行计划对于您通常使用的变量种类来说可能是完全次优的


如果您发现可以从ManagementStudio执行一个存储过程,执行该过程需要2秒,但在应用程序中执行相同的操作需要20秒,那么这可能是参数嗅探的结果。

在DB2中,实际情况可能正好相反。SQL例程中的语句是在编译例程时准备的。动态SQL语句(如示例中所示)是在例程运行时准备的

因此,动态语句的准备将考虑最新的表和索引统计信息以及其他编译环境设置,如隔离级别,而静态语句将使用在例程编译或最新绑定期间有效的统计信息

如果您想要稳定的执行计划,请使用静态SQL。如果您的统计信息经常更改,您可能希望使用动态SQL(或者确保相应地重新绑定例程的包)


同样的逻辑也适用于Oracle PL/SQL例程,尽管重新编译静态SQL的方法不同——您需要使相应的例程无效。

bah,这是一分钟前标记的
SQL server
,对吗?这里更一般的信息仍然是相关的,所以不管怎么说,我都会把它留在这里,忽略对ManagementStudio的引用……是的,实际上我不认为我使用什么样的数据库会对我的问题产生多大影响。幸运的是,之前贴错了标签,或者我无法亲自阅读你的回答,我不认为db有什么关系…指出如果我错了,你使用的具体产品肯定会影响你所能说的!这些东西总是高度特定于供应商,SQL Server的某些东西可能根本不适用于DB2或Oracle(反之亦然)@我同意marc_的说法,例如我的示例代码只能在db2中运行。但我的问题有点笼统,因为许多流行的数据库都支持即席SQL和过程。我想不同db的处理键差别不大。如果我的问题的答案确实取决于所使用的具体产品,例如不需要在SQL server中准备,但它在DB2中工作,那么我想知道它们之间的异同。这些对我有帮助。无论如何,我还没有完成你的答案张贴之前。至少在阅读时,我真的认为这很有帮助——“这方面的一般信息仍然是相关的”。@marc_s您介意告诉我您所知道的db产品如何以不同的方式处理过程中的语句,作为下面的答案吗?根据它们的工作原理,我应该(不)在一些具体的产品中这样做吗respectively@OGHaza-哪一部分让你困惑?创建例程时,静态SQL只准备一次;每次t时都准备动态SQL