zoukankan      html  css  js  c++  java
  • 存储过程中引用的常规表,临时表以及表变量是否会导致存储过程的重编译

    在存储过程中,经常要引用一些表来存储一些中间数据,用完即删。对于这个中间表,用常规表,临时表或者表变量有什么区别呢?

    下面我们看一下这三种中间表是否会造成执行计划的重编译。

    首先打开sql server profile,监控存储过程。

    1.建第一个存储过程,在存储过程中创建常规表TT1

    复制代码
    CREATE PROCEDURE TEST1_PRO
    AS 
    BEGIN 
        CREATE TABLE TT1(
        ID INT IDENTITY,
        NAME VARCHAR(10)
        )
    
        INSERT INTO TT1
        VALUES ('name1')
    
        select * From TT1
    
        DROP TABLE TT1
    END
    复制代码

    下面调用存储过程

    --Firsttime
    EXEC TEST1_PRO

    查看sql server profile的如下截图:

    可以看到在存储过程中创建常规表,会造成两次重编译。第一个编译是由于常规表的新建之后的DML操作造成的,第二个重编译是查询新建表导致的执行计划的编译。

    下面我们第二次调用该存储过程

    --SecondTime
    EXEC TEST1_PRO

    查看sql server profile的如下截图:

    可以看到第二次调用存储过程跟第一次调用存储过程都会造成两次重编译。

    2.建第二个存储过程,在存储过程中创建临时表#TT1

    复制代码
    CREATE PROCEDURE TEST2_PRO
    AS 
    BEGIN 
        CREATE TABLE #TT1(
        ID INT IDENTITY,
        NAME VARCHAR(10)
        )
    
        INSERT INTO #TT1
        VALUES ('name1')
    
        select * From #TT1
        DROP TABLE #TT1
    END
    复制代码

    调用存储过程

    --Firsttime
    EXEC TEST2_PRO

    查看sql server profile的如下截图:

    可以看到第一次调用TEST2_PRO存储过程跟第一次调用TEST1_PRO的时候造成的重编译是一样的,两次重编译。

    我们再次调用该存储过程

    --SecondTime
    EXEC TEST2_PRO

    查看sql server profile的如下截图:

    可以看到当存储过程再次被执行时,没有发生重编译。临时表只能用于存储过程范围之内,无法在存储过程范围之外使用,因此其架构在多次执行之后并未发生任何改变,从而可以在存储过程后续执行期间重用现有的执行计划。

    3.建第三个存储过程,在存储过程中创建表变量@TT1

    复制代码
    CREATE PROCEDURE TEST3_PRO
    AS 
    BEGIN 
    DECLARE @TT1 TABLE(
        ID INT IDENTITY,
        NAME VARCHAR(10)
        )
    
        INSERT INTO @TT1
        VALUES ('name1')
    
        select * From @TT1
    
    END
    复制代码

    调用存储过程

    --Firsttime
    EXEC TEST3_PRO

    查看sql server profile的如下截图:

    可以看到对于存储过程中创建表变量,第一次调用该存储过程并没有发生重编译。

    再次调用存储过程

    --SecondTime
    EXEC TEST3_PRO

    查看sql server profile的如下截图:

    再次调用存储过程之后,也没有发生重编译,可以看到当用表变量当存储过程的中间表,不会造成存储过程的重编译。

    由于表变量不会写日志,不会造成锁开销,不能在Declare之外创建主键索引等,因此表变量不会造成架构的变化,从而不会造成重编译。该存储过程的执行计划已经在创建存储过程的时候生成了,因此之后执行的存储过程不会造成执行计划的重编译。

    综上所述,我认为在存储过程中中间表需要存储少量数据时,创建表变量来存储中间数据是开销最小的。

    如果大家有什么问题可以提出来,相互交流,谢谢!

  • 相关阅读:
    数组有没有length()这个方法? String有没有length()这个方法?
    序列化接口的id有什么用?
    如何进行Hibernate的性能优化?
    构造器Constructor是否可被override?
    Collection框架中实现比较要实现什么接口?
    ArrayList如何实现插入的数据按自定义的方式有序存放?
    Java中会存在内存泄漏吗,请简单描述?
    List 和 Map 区别?
    面向对象的特征有哪些?
    垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?
  • 原文地址:https://www.cnblogs.com/lykbk/p/dfdfdfdfdfdf4545454545454.html
Copyright © 2011-2022 走看看