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之外创建主键索引等,因此表变量不会造成架构的变化,从而不会造成重编译。该存储过程的执行计划已经在创建存储过程的时候生成了,因此之后执行的存储过程不会造成执行计划的重编译。

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

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

  • 相关阅读:
    利用python爬虫关键词批量下载高清大图
    多源最短路径算法—Floyd算法
    Dijkstra算法详细(单源最短路径算法)
    写博客没高质量配图?python爬虫教你绕过限制一键搜索下载图虫创意图片!
    并查集(不相交集合)详解与java实现
    AVL树(二叉平衡树)详解与实现
    二叉树——前序遍历、中序遍历、后序遍历、层序遍历详解(递归非递归)
    CSS基础总结
    HTML基础总结
    JavaSE 软件工程师 认证考试试卷3
  • 原文地址:https://www.cnblogs.com/tianguook/p/5244237.html
Copyright © 2011-2022 走看看