AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 187276
Accepted
Edmund
Edmund
Asked: 2017-09-30 05:17:24 +0800 CST2017-09-30 05:17:24 +0800 CST 2017-09-30 05:17:24 +0800 CST

如何重新编译 SQL Server 数据库中的所有存储过程和表值函数?

  • 772

在 SQL Server 数据库sp_recompile上可以运行一个存储过程来更新执行计划。我想在数据库中的所有存储过程上运行它。另外,我想在所有表值函数上运行它的等价物,但我不知道要运行哪个 sys 过程。

是否可以在不sp_recompile为 SQL Server Management Studio 中的所有存储过程名称手动输入一行的情况下执行此操作?同样对于表值函数?

我相信我需要这样做,因为 VM SQL Server 的内存显着增加,但我只看到执行时间略有增加。执行计划显示 80% 以上的运行时间是在聚集索引搜索上,所以我认为我无法做更多的事情来优化存储过程。

sql-server stored-procedures
  • 6 6 个回答
  • 24160 Views

6 个回答

  • Voted
  1. Best Answer
    David Spillett
    2017-09-30T05:54:15+08:002017-09-30T05:54:15+08:00

    如果您认为这会有所帮助,您可以sp_recompile通过使用游标为每个内容生成临时 SQL 并运行它来运行所有内容:

    DECLARE C CURSOR FOR (SELECT [name] FROM sys.objects WHERE [type] IN ('P', 'FN', 'IF'));
    DECLARE @name SYSNAME;
    OPEN C;
    FETCH NEXT FROM C INTO @name;
    WHILE @@FETCH_STATUS=0 BEGIN
        EXEC sp_recompile @name;
        FETCH NEXT FROM C INTO @name;
    END;
    CLOSE C;
    DEALLOCATE C;
    

    或者您可以生成临时 SQL 并通过 运行它EXEC,需要更少的代码,这可能会稍微更有效:

    DECLARE @sql NVARCHAR(MAX) = '';
    SELECT @sql += 'EXEC sp_recompile '''+[name]+''''+CHAR(10) FROM sys.objects WHERE [type] IN ('P', 'FN', 'IF');
    EXEC (@sql);
    

    (虽然我发现这种形式有时会因为看起来基于集合但迭代地构建字符串而不是标准的 SQL 模式而引起人们的注意)

    另一组可能与此处类似的对象是视图。您可以类似地将它们标记为需要重新评估,以确保存储的计划和其他元数据不会过时sp_refreshview,只需对上面显示的游标或临时 SQL 方法进行小的修改:

    DECLARE @sql NVARCHAR(MAX) = '';
    SELECT @sql += 'EXEC sp_refreshview '''+[name]+''''+CHAR(10) FROM sys.objects WHERE [type] IN ('V');
    EXEC (@sql);
    

    执行计划显示 80% 以上的运行时间是在聚集索引搜索上,所以我认为我无法做更多的事情来优化存储过程。

    有时优化比优先搜索而不是扫描等等,有时索引扫描比许多执行搜索操作更有效,并且计算您正在查看的百分比数字的成本估计是(估计)在最好的(一个有用的指南,但有时完全不准确)。

    虽然“投入更多内存”可以帮助解决一些数据库性能问题,至少是暂时的,但如果您的瓶颈受 CPU 限制而不是内存和/或 IO 限制,那么添加更多内存将几乎没有效果。

    • 9
  2. SQL Police
    2020-04-17T00:44:36+08:002020-04-17T00:44:36+08:00

    该解决方案基于此处的另一个答案,但考虑了模式并考虑了名称中的特殊字符。 它重新编译所有模式中的所有过程、函数和内联函数。

    create procedure dbo.RecompileAllProcedures
    as
    begin
        declare cur cursor for 
        (
            select quotename(s.name) + '.' + quotename(o.name) as procname
            from 
               sys.objects o
               inner join sys.schemas s on o.schema_id = s.schema_id
            where  o.[type] in ('P', 'FN', 'IF')
        );
    
        declare @procname sysname;
    
        open cur;
        fetch next from cur into @procname;
        while @@fetch_status=0 
        begin
            exec sp_recompile @procname;
            fetch next from cur into @procname;
        end;
        close cur;
        deallocate cur;
    end;
    

    然后可以按如下方式调用它:

    exec dbo.RecompileAllProcedures
    

    PS:我是 Allman 编码风格的忠实粉丝;)

    编辑:quotename在名称包含方括号的情况下,使用更安全的方法改进了程序。

    • 7
  3. Erik Darling
    2017-09-30T05:26:40+08:002017-09-30T05:26:40+08:00

    如果您添加内存(即使它是热添加到虚拟机),并增加最大服务器内存以匹配,您的计划缓存将被清除。

    这实际上是在“重新编译”您提到的所有这些内容,因为它们不会在缓存中存储计划以供重复使用。SQL Server 将不得不构建一个新的。

    不过,您可能从未设置过 Max Server Memory。如果您对此不确定,可以运行DBCC FREEPROCCACHE以清除计划缓存。

    您在生产中执行此操作需要您自担风险。我不能保证新计划会更好。

    内存并不能解决 SQL Server 中的所有性能问题,Seek 不一定是性能调整的终点。

    如果您需要有关特定查询的帮助,您应该提出一个单独的问题。

    • 5
  4. Michielsen Leo
    2021-12-10T08:00:59+08:002021-12-10T08:00:59+08:00

    如果您有不同模式中的对象,则更新语句

    declare @sql nvarchar(max) = (
    select String_Agg(
        'exec sp_recompile '''+
        OBJECT_SCHEMA_NAME(object_id)+'.'+[Name]+'''', Char(10))
    from sys.Objects where [Type] in ('P', 'FN', 'IF'));
    
    exec (@sql);
    
    • 1
  5. Homero Rivera
    2020-07-08T13:56:52+08:002020-07-08T13:56:52+08:00

    我知道这是一个老问题,但是您可以遵循另一种记录在案的方法。

    查询优化器在决定使用当前查询执行计划或编译新 QEP 之前检查表的统计信息。

    QO 已经“执行”统计信息来决定 QEP,但您可以自己更新统计信息,这会自动发出 QO 在下次运行时重新编译的信号。

    这样您就可以避免运行存储过程只是为了重新编译它,因为它将在下次运行时重新编译。您可以逐表更新统计信息表,也可以使用以下命令更新整个数据库

    EXEC sp_updatestats;
    

    来源:

    https://learn.microsoft.com/en-us/sql/relational-databases/statistics/statistics?view=sql-server-ver15

    https://learn.microsoft.com/en-us/sql/t-sql/statements/update-statistics-transact-sql?view=sql-server-ver15

    • 0
  6. N8allan
    2020-05-09T13:12:27+08:002020-05-09T13:12:27+08:00

    基于David Spillett 的回答,如果运行 SQL Server 2017 或更高版本,您可以使用String_Agg 函数并进一步简化:

    declare @sql nvarchar(max) = (select String_Agg('exec sp_recompile '''+[Name]+'''', Char(10)) from sys.Objects where [Type] in ('P', 'FN', 'IF'));
    exec (@sql);
    
    • -1

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve