一个查选优化的例子,转--SQL Server中存储过程比直接运行SQL语句慢的原因
原来文地址:http://blog.csdn.net/emili/archive/2008/03/17/2192081.aspx
------------------------
大概记录下先,有时间再整理,最后优化的代码如下:
表结构猜测
FACT(用户号,操作时间,动作)
FACT应该是跟踪用户操作的一张表,
现在需要根据这张表记录的数据来统计,给定时间(今天)一共有多少个用户活动过(上线过)以及这些用户中新用户有多少个.
这个存储过程每天定时远行,将昨天的的统计数据插入到表PRT_IM_USERINFO_DAILY中
========优化前的存储过程
CREATE PROCEDURE [dbo].[pro_ImAnalysis_daily]
@THEDATE VARCHAR(30)
AS
BEGIN
IF @THEDATE IS NULL
BEGIN
SET @THEDATE=CONVERT(VARCHAR(30),GETDATE()-1,112);
END
DELETE FROM RPT_IM_USERINFO_DAILY WHERE THEDATE=@THEDATE;
INSERT RPT_IM_USERINFO_DAILY (THEDATE,ALLUSER,NEWUSER)
SELECT AA.THEDATE,ALLUSER,NEWUSER
FROM
( ( SELECT THEDATE,COUNT(DISTINCT USERID) ALLUSER
FROM FACT
WHERE THEDATE=@THEDATE
GROUP BY THEDATE
) AA
LEFT JOIN
(SELECT THEDATE,COUNT(DISTINCT USERID) NEWUSER
FROM FACT T1
WHERE NOT EXISTS(
SELECT 1
FROM FACT T2
WHERE T2.THEDATE<@THEDATE
AND T1.USERID=T2.USERID)
AND T1.THEDATE=@THEDATE
GROUP BY THEDATE
) BB
ON AA.THEDATE=BB.THEDATE);
GO
由于“Parameter sniffing”的特性,导致上面的存储过程执行缓慢,具体请看上面给出的原文地址,下面分析新存储过程:
========优化后的存储过程
ALTER PROCEDURE [dbo].[pro_ImAnalysis_daily]
@var_thedate VARCHAR(30)
AS
BEGIN
declare @THEDATE VARCHAR(30)
IF @var_thedate IS NULL
BEGIN
SET @var_thedate=CONVERT(VARCHAR(30),GETDATE()-1,112);
END
SET @THEDATE=@var_thedate;
DELETE FROM RPT_IM_USERINFO_DAILY WHERE THEDATE=@THEDATE;
INSERT RPT_IM_USERINFO_DAILY(THEDATE,ALLUSER,NEWUSER)
select @thedate as thedate,
count(distinct case when today>0 then userid else null end) as alluser,
count(distinct case when dates=0 then userid else null end) as newuser
from
(
select userid,
count(CASE WHEN thedate>=@thedate then null else thedate end) as dates,
count(case when thedate=@thedate then thedate else null end) as today
from FACT
group by userid
)as fact
GO
根据用户号分组, 统计thedate>=@thedate 等价于(thedate<@thedate then thedate else null)即过去登陆(活动过)的统计进来,thedate=@thedate 则表示今天活动过统计进来,那么下面的分组统计就形成这样的数据集:
T1 (用户ID,过去活动次数,今天活动次数)
用户要么过去登录过要么今天登录过,因此T1.[过去活动次数]与T1.[今天活动次数],绝对不能同时为零,于是外围的count 第二句,当 dates=0时,那么就绝对是新用户了.
注意:这里成立的条件是现在是当前时间,如果我今天统计昨天的,全部登录用户跟最新用户,那么如果今天有Userid新进来那么就有可能导致T1.[过去活动次数]与T1.[今天活动次数]都是零的情况,那么dates=0就不能作为判断新用户的依据了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述