mysql 存储过程 compile_SQL SERVER 临时表导致存储过程重编译(recompile)的一些探讨_MySQL...

article/2025/10/6 16:31:30

SQLSERVER为了确保返回正确的值,或者处于性能上的顾虑,有意不重用缓存在内存里的执行计划,而重新编译执行计划的这种行为,被称为重编译(recompile)。那么引发存储过程重编译的条件有哪一些呢?下面罗列了一些导致重编译(recompile)的条件:

- 对查询所引用的表或视图进行更改(ALTER TABLE 和 ALTER VIEW)。

- 对执行计划所使用的任何索引进行更改。

- 对执行计划所使用的统计信息进行更新,这些更新可能是从语句(如 UPDATE STATISTICS)中显式生成,也可能是自动生成的。

- 删除执行计划所使用的索引。

- 显式调用 sp_recompile。

- 对键的大量更改(其他用户对由查询引用的表使用 INSERT 或 DELETE 语句所产生的修改)。

- 对于带触发器的表,插入的或删除的表内的行数显著增长。

- 使用 WITH RECOMPILE 选项执行存储过程。

- 有些DBCC FREEPROCCACHE;分离、附加数据库、数据升级也会清除内存里缓存的执行计划

好了,切入到今天我们要关注的问题:临时表的数据变化导致存储过程重编译问题,其实临时表的数据变化导致存储过程重编译实质上是因为临时表的数据变化,导致了临时表统计信息的自动更新,从而引起的重编译。那么触发临时表的统计信息的更新的条件或阀值是什么呢?说来也简单,就是下面一个这个公式(n表示变更前临时表的数据记录数,确切的说是上一次采集统计信息时临时表的记录数)

Temporary table

If n < 6, RT = 6.

If 6 <= n <= 500, RT = 500.

If n > 500, RT = 500 + 0.20 * n.

有个网友说存储过程中的临时表数据变更的阀值有问题:他的原话如下

If n < 6, Recompilation threshold = 6.

If 6 <= n <= 500, Recompilation threshold = 500.

上面这两个区间没有问题。但是大于500的之后,根本就不是变化大于20%之后再重编译。看了他提出的问题,其实我也不是特肯定,毕竟没有实际验证过。实践才是检验整理的唯一标准,那么我们就开始做实验吧,首先准备一下测试环境(Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (X64) ).脚本如下所示:

USE MyDBA;

GO

IF EXISTS(SELECT 1 FROM sys.sysobjects WHERE id=object_id(N'[dbo].[TEST]') AND OBJECTPROPERTY(id, N'IsTable')=1 )

BEGIN

DROP TABLE dbo.TEST;

CREATE TABLE TEST

(

ID INT IDENTITY(1, 1) ,

NAME VARCHAR(40) ,

CONSTRAINT PK_TEST PRIMARY KEY(ID)

)

END

GO

INSERT INTO TEST VALUES(NEWID())

GO 10000

CREATE PROCEDURE Usp_Recompile_TEST(@Index INT)

AS

BEGIN

CREATE TABLE #T(ID INT , NAME VARCHAR(40));

INSERT INTO #T SELECT ID, NAME FROM TEST WHERE ID <=@Index;

SELECT m.* FROM #T m INNER JOIN TEST n ON m.ID = n.ID

END

GO

准备好测试环境后,那么此时我们打开SQL Server工具SQL Server Profiler,选择“SP:Recompile”和“SP:Complete”事件,然后取消一些选择列,仅仅选择一些需要的列,例如 EventClass、TextData等。如下所示

144P204H54E0-2W25.jpg

开启Profile跟踪后,我们打开一个会话窗口,勾选“包括实际的执行计划”,然后再窗口执行下面SQL语句

EXEC dbo.Usp_Recompile_TEST 1;

如下所示,实际的执行计划中,我们看到“估计行数”和“实际行数”是一致的。

144P204HY060-31N7.jpg

EXEC dbo.Usp_Recompile_TEST 2;

EXEC dbo.Usp_Recompile_TEST 6;

执行上面两个语句,我们会发现“估计行数”与“实际行数”开始出现偏差,因为数据库对临时表#T没有最新的统计信息,还是上一次收集的统计信息时的数据(1行数据)

144P204I1W50-43362.jpg

EXEC dbo.Usp_Recompile_TEST 7; 此时已经触发了对临时表统计信息的采集更新(请见后面阐述)。

144P204I421Z-55242.jpg

EXEC dbo.Usp_Recompile_TEST 130;

EXEC dbo.Usp_Recompile_TEST 500;

EXEC dbo.Usp_Recompile_TEST 506;

EXEC dbo.Usp_Recompile_TEST 507;

那么执行上面SQL语句,130我们确信不会导致临时表#T去更新统计信息,501会触发#T表的统计信息更新吗? 如果不会触发,那么确切的值是多少呢?答案是507,如下截图所示:

144P204IDK0-620X.jpg

想必有些人会说,我实验的结果不一样哦(啪啦啪啦说一大堆),那么你是否真正的理解了下面公式呢? n表示临时表变跟前的记录数(确切的说是统计信息采集时的记录数),后面的RT表示变跟的记录数。

Temporary table

If n < 6, RT = 6.

If 6 <= n <= 500, RT = 500.

If n > 500, RT = 500 + 0.20 * n.

由于我第一次执行的是EXEC dbo.Usp_Recompile_TEST 1,那么数据库的记录数为1,那么1+ 6 =7; 也就是上图EXEC dbo.Usp_Recompile_TEST 7时才触发临时表#T的统计信息更新,而为什么是507(7+500=507)呢,因为最后一次统计信息的采集,临时表#T的记录数为7 ,所以7+500=507,是否有点不解,那么你按我这个SQL执行一遍,然后用Profile跟踪、你会看到下面结果,如果还不太明白,结合截图好好理解一下:

DBCC FREEPROCCACHE;

EXEC dbo.Usp_Recompile_TEST 2;

EXEC dbo.Usp_Recompile_TEST 6;

EXEC dbo.Usp_Recompile_TEST 7;

EXEC dbo.Usp_Recompile_TEST 8;

144P204IZ620-J320.jpg

如果还没有理解的话,我的表达能力已到极限了,自己再好好琢磨一下吧! 那么接下来才是我们重点想要验证、测试的。

DBCC FREEPROCCACHE;

EXEC dbo.Usp_Recompile_TEST 501;

此时临时表#T的记录数为501,那么当临时表#T里面的记录数变更了多少时,才会触发统计信息的更新呢? 由于是插入,那么根据公式应该是501 + (500 + 0.2*501) = 1101.2 ,那么应该是1101,即使是1100也不会变化。下面SQL Server Profile可以验证我们的推测

EXEC dbo.Usp_Recompile_TEST 1100;

EXEC dbo.Usp_Recompile_TEST 1101;

如果我们继续使用该存储过程,那么当参数为什么值时才会触发统计信息更新呢? 1101 +(500+0.2*1101)=1821.2,也就是说必须是1821才会触发统计信息更新,下面SQL Server Profile的截图也验证了我们的推测。

EXEC dbo.Usp_Recompile_TEST 1300;

EXEC dbo.Usp_Recompile_TEST 1320;

EXEC dbo.Usp_Recompile_TEST 1321;

EXEC dbo.Usp_Recompile_TEST 1820;

EXEC dbo.Usp_Recompile_TEST 1821;

144P204J10940-T2K.jpg

所以综上述实验验证,SQL SERVER 临时表导致存储过程重编译(recompile)的那些阀值确实是正确的,也是没有问题的。当然如有疏漏或不对的地方,敬请指出。

本文原创发布php中文网,转载请注明出处,感谢您的尊重!


http://chatgpt.dhexx.cn/article/9MaDwGas.shtml

相关文章

Qt recompile with -fPIC

Qt编译时提示&#xff1a; relocation R_X86_64_32 against ‘.rodata’ can not be used when making a PIE object: recompile with fPIC 于是百度&#xff0c; 找了很久找到一篇能够解决我这问题的帖子 在这里面的参考文档中提到&#xff0c;从Ubuntu16.10版本开始默认启用P…

IDEA安装JRebel实现热部署,自动reload和recompile

利用JRebel插件实现代码及时编译功能&#xff0c;帮助我们在开发过程中节省项目重启时间&#xff0c;提高开发效率。JRebel插件实现及时编译&#xff0c;帮助我们在开发过程中节省项目重启时间&#xff0c;提高开发效率。 一、安装 插件安装流程&#xff1a; 1.下载安装JRebel插…

WITH RECOMPILE和OPTION(RECOMPILE)区别

在考虑重编译T-SQL(或者存储过程)的时候,有两种方式可以实现强制重编译(前提是忽略导致重编译的其他因素的情况下,比如重建索引,更新统计信息等等),  一是基于WITH RECOMPILE的存储过程级别重编译,另外一种是基于OPTION(RECOMPILE)的语句级重编译。  之前了解的比较…

内网穿透群晖NAS:实现无公网IP远程访问群晖 2/2

系列文章 内网穿透群晖NAS&#xff1a;免费安装cpolar群晖套件 1/2内网穿透群晖NAS&#xff1a;实现无公网IP远程访问群晖 2/2 上一篇 内网穿透群晖NAS&#xff1a;免费安装cpolar群晖套件 1/2 在上一篇介绍里&#xff0c;我们在群晖系统中成功安装了图形化界面的cpolar&#…

群晖设置公网ipv6方式域名解析访问

1.环境说明 上网&#xff1a;电信光猫tplink路由器(电信送的&#xff09; 群晖&#xff1a;DSM 7.1.1-42962 Update 2 域名服务商&#xff1a;腾讯云 2.光猫设置 2.1 获取光猫超级用户密码 拨打电信10000号 2.2 修改光猫为桥接模式 略 3.路由器设置 3.1 路由器拨号上网…

群晖 阿里云ddns_群晖QuickConnect功能详解

先来了解下什么是QuickConnect,这是群晖的一个远程访问功能, 有这个功能直接注册一个QuickConnect账号就可以远程访问了, 这样就不需要你的宽带是否有公网ip, 也不需要配置路由器端口映射, 就可以轻松的实现外网访问。 上图的 http://quickconnect.to/vip 外网在电脑浏览器…

IPv6/IPv4 + aliddns 实现黑群晖外网控制和访问

前言 一直想弄台黑群NAS&#xff0c;但因为穷&#xff01;一直没入&#xff0c;一直用的是玩客云&#xff0c;但玩客云满足不了我的需求&#xff0c;但正好搭上蜗牛星际的车&#xff01; J19004G内存16G固态4盘位千兆网口才380元&#xff0c;性价比是真的高&#xff0c;再买两…

群晖NAS配置DNSPodDDNS实现外网访问(仅适用于阿里云域名)

创作立场声明&#xff1a;本文只是单纯的经验分享&#xff0c;没有任何恰饭行为!转载前请联系作者授权&#xff0c;并附上此文章链接! 前言 本文将详解如何使用群晖NAS自带的DDNS功能来实现腾讯云DNSPod动态域名解析。 设置你的域名DNS服务器到DNSPod 登录阿里云控制台&…

【宇麦科技】腾xun云登场,群晖NAS自定义域名教程来啦~

如今网盘的使用成本越来越高&#xff0c;更多的人选择搭建自己的家庭 NAS 服务器。 NAS 可以用来做大容量存储、文件备份、文件下载、相册同步&#xff0c;甚至可以搭建网站、搭建自己的笔记以及邮件服务。 NAS 一般都安装在家里&#xff0c;那么出门在外应该如何远程访问家里的…

群晖NAS的公网、NAT、DDNS、证书等配置一

一、群辉NAS应用场景 你是否有过这样的需求? 1. 远程办公 日常的工作资料太多太杂乱,换个电脑根本没法工作?团队间资料共享太麻烦?Drive套件这个远程办公神器都能解决。 我的文件相当于远程的“我的文档”,“团队文件”是可以与团队成员共享。在PC端和手机端都可以方便…

群晖NAS教程(二十一)、利用Docker安装DDNS动态域名解析,自动更新域名解析到公网IP(支持阿里云、腾讯云dnspod、Cloudflare、华为云)

群晖NAS教程(二十一)、利用Docker安装DDNS动态域名解析&#xff0c;自动更新域名解析到公网IP(支持阿里云、腾讯云dnspod、Cloudflare、华为云) 为了更好的浏览体验&#xff0c;欢迎光顾勤奋的凯尔森同学个人博客http://www.huerpu.cc:7000 一、下载镜像与配置启动参数 在群…

群晖外网访问终极解决方法:IPV6+阿里云ddns+ddnsto

写在前面的话 受够了群晖的quickconnet的小水管了&#xff0c;急需一个新的解决方法&#xff0c;这是后发现移动没有公网IP&#xff0c;只有ipv6&#xff08;公网的&#xff09;&#xff0c;时候有小伙伴要问&#xff0c;要是没有ipv6就没办法访问群晖了吗&#xff1f; 不&…

群辉默认DDNS功能解析阿里云-自定义服务商

前言 前不久买了个群辉NAS发现群辉DDNS不能解析阿里云&#xff0c;后来找了很多教程都是部署Docker或使用其他平台转发一下&#xff0c;然而这些平台还要注册&#xff0c;我就在想我自己可不可以实现不需要注册就可以使用的DDNS&#xff0c;毕竟咱也是干这个的。 然后我就去上…

一文搞懂“如何通过群晖+DNSPod DDNS搭建私有云服务?”

DNSPod春节特惠3折起 买解析就送CDN&#xff0c;最高60TB CDN让你带回家 &#x1f449;&#x1f3fb;购买入口 近期很多DIY私有云玩家私聊D妹“我想在外网访问家庭网络&#xff0c;怎么搞&#xff1f;”&#xff0c;“如何将动态IP映射到一个固定的域名解析服务上&#xff1f;”…

[NAS] Synology (群晖) DSM7.0 使用自定义供应商DDNS

简介 找了很多教程都是部署Docker或使用其他平台转发一下&#xff0c;然而这些平台还要注册, 实际阿里云是有阿里云OpenSDK 可以支持的&#xff0c;本来想自己写了一个&#xff0c;后面发现有人已经实现了, 就用了一个开发者的DDNS服务, https://ddns.bkood.com/, 在这里非常感…

群晖设置腾讯云ddns显示认证失败的两种解决办法【实测第二种成功了】

群晖腾讯云ddns显示认证失败 背景&#xff1a;问题&#xff1a;前提条件解决办法一&#xff1a;群晖自带的ddns解析步骤1&#xff1a;获取 API 密钥信息步骤2&#xff1a;群晖&#xff08;Synology&#xff09;NAS 配置 DDNS 解决办法二&#xff1a;利用Docker安装DDNS动态域名…

群晖IPv6/ddns-go/域名解析设置内网穿透方案

前言 群晖的内网穿透有很多方案&#xff0c;外网IPv4(这个现在很难搞到了)&#xff0c;中间服务器搭建Tunnel隧道&#xff0c;frp等方案(网速慢&#xff0c;流量限制&#xff0c;需另购服务器)&#xff0c;第三方服务花生壳等(按量付费&#xff0c;速度问题)。 本篇介绍的是 …

群晖QuickConnect与DDNS之间有何区别?

群晖QuickConnect与DDNS都是为了实现外网访问群晖NAS设备&#xff0c;它们2个之间有什么区别呢&#xff1f; DDNS访问速度更快 功能是一样的&#xff0c;但是实现的网络协议本质上有着不同。QuickConnect可让群晖设备通过Synology QuickConnect服务器与群晖产品&#xff08;如…

外网访问群晖设置ddns教程

本来之前用的是华硕的路由器&#xff0c;里面自带ddns功能&#xff0c;但是最近不懂是硬件问题还是固件问题&#xff0c;测网速是没问题的&#xff0c;就是打游戏的时候会忽然卡一下&#xff0c;跳延迟&#xff0c;忍无可忍&#xff0c;最后用了gen10上面装的openwrt软路由&…

群晖DDNS和端口转发等相关讲解

文章目录 废话篇前言本文知识概要域名和IP地址的了解域名解析内网IP和外网IPDDNS是什么&#xff1f;群晖如何设置DDNS端口转发后言协助改进 废话篇 本篇文章为原创文章&#xff0c;转载请注明出处&#xff0c;感谢。 本人也有个人博客&#xff1a;李蜀博客 更多原创文章&…