【原创】项目性能优化全纪录(一) 存储过程优化
2011-08-09 14:24
225 查看
公司的项目中需要增加一个对信息亭点击量进行实时统计的子项目。前台程序点击的Log数据会被保存到服务器上的一张AppLog表中。
信息亭每天的点击量很高,可想而知AppLog表中数据量得有多大。据初步估算,一年可以产生上亿条点击纪录。因而数据统计的性能问题一直困扰着我。
七夕节在家没事干,就看了一下微软的WebCast中asp.net优化的那部分视频同时还看了一本Richhard Kiessing写的《构建高性能可扩展Asp.net网站》。
星期一一上班就开始着手对项目进行优化。
废话不多说先看Applog的表结构:
所作的统计基本上都是根据EventTime来统计Logcode的数量。其中有一个最耗费性能的统计就是根据某一个时间段按照用户给出的统计条件来统计点击数量。
项目第一个版本的存储过程是这样写的:
其原理是通过master数据库生成一张时间段的临时表,然后再利用Applog表和master表进行右连接之后,在进行分组统计查询。
我统计一次从2010年1月1日到2011年11月2日,SQLServer执行的时间是1分51.555秒。结果如下:
通过思考,我发现可以先根据时间段来拆分SQL语句,然后使用union all在连接起来查询,这样的话可以减少运算3次笛卡尔积性能必定能够提升。其具体实现如下:
事实证明我的想法是对的,执行同样的查询得到相同的结果SQL Server只需要1.319秒,性能提升了98.82%.如下图所示:
通过这次成功的优化,我发现做写程序做项目不仅仅是把项目完成就OK了。旧项目里面还有很多东西需要考虑和优化,只有不断的优化才能使项目运行的更稳定才能使自己得到更大的提升,这就是“温故而知新”的重要意义吧。
信息亭每天的点击量很高,可想而知AppLog表中数据量得有多大。据初步估算,一年可以产生上亿条点击纪录。因而数据统计的性能问题一直困扰着我。
七夕节在家没事干,就看了一下微软的WebCast中asp.net优化的那部分视频同时还看了一本Richhard Kiessing写的《构建高性能可扩展Asp.net网站》。
星期一一上班就开始着手对项目进行优化。
废话不多说先看Applog的表结构:
所作的统计基本上都是根据EventTime来统计Logcode的数量。其中有一个最耗费性能的统计就是根据某一个时间段按照用户给出的统计条件来统计点击数量。
项目第一个版本的存储过程是这样写的:
use CMS if Exists(select name from sysobjects where name='GetGroupClicksByDate' And type='p') drop procedure dbo.GetGroupClicksByDate go create proc dbo.GetGroupClicksByDate @date_begin datetime, @date_end datetime, @int_interval int, @var_projectName varchar(32) as declare @int_datecount int if @date_begin is not null and @date_end is not null and @int_interval is not null and @var_projectName<>'' begin set @int_datecount= datediff(hh,@date_begin,@date_end) if @int_datecount % @int_interval <>0 set @date_end=DATEADD(HOUR, ((@int_datecount/@int_interval)+1)*@int_interval,@date_begin) select r.StartTime,r.EndTime, ISNULL(count(t.LogCode),0) as SumCount from applog t right join ( select h.LogCode, DATEADD(HOUR,number*@int_interval,@date_begin) as StartTime, DATEADD(HOUR,(number+1)*@int_interval,@date_begin) as EndTime from master..spt_values, (select distinct LogCode from applog where applog.ProjectName=@var_projectName )h where type='P' and DATEADD(HOUR,(number+1)*@int_interval,@date_begin)<=@date_end ) r on t.LogCode =r.LogCode and t.EventTime >= r.StartTime and t.EventTime< r.EndTime group by r.StartTime,r.EndTime order by r.StartTime end
其原理是通过master数据库生成一张时间段的临时表,然后再利用Applog表和master表进行右连接之后,在进行分组统计查询。
我统计一次从2010年1月1日到2011年11月2日,SQLServer执行的时间是1分51.555秒。结果如下:
通过思考,我发现可以先根据时间段来拆分SQL语句,然后使用union all在连接起来查询,这样的话可以减少运算3次笛卡尔积性能必定能够提升。其具体实现如下:
use CMS if Exists(select name from sysobjects where name='GetGroupClicksByDate' And type='p') drop procedure dbo.GetGroupClicksByDate go /* Written By:WMJ WriteDate :2011-08-19 Function: Get the clicks by time interval */ create proc dbo.GetGroupClicksByDate @date_begin datetime, @date_end datetime, @int_interval int, @var_projectName varchar(32) as declare @var_SQL varchar(MAX) declare @int_datecount int declare @int_datecal int declare @date_temptime datetime if @date_begin is not null and @date_end is not null and @int_interval is not null and @var_projectName<>'' begin set @int_datecount= datediff(hh,@date_begin,@date_end) --Calcultate the total hours count set @int_datecal=@int_datecount/@int_interval --Calculate the total datarangge count if @int_datecount % @int_interval <>0 begin set @date_end=DATEADD(HOUR, ((@int_datecount/@int_interval)+1)*@int_interval,@date_begin) end set @date_temptime=DATEADD(HOUR,@int_interval,@date_begin) set @var_SQL='select count(*) as Sumcount,'''+CONVERT(varchar, @date_begin,120)+''' as StartTime,'''+CONVERT(varchar,@date_temptime ,120)+''' as EndTime from applog where applog.EventTime> '''+CONVERT(varchar, @date_begin,120) set @date_begin=@date_temptime set @var_SQL=@var_SQL+ ''' and applog.EventTime <='''+CONVERT(varchar, @date_begin ,120)+''' and applog.ProjectName= '''+@var_projectName+''' ' while @int_datecal>0 begin set @date_temptime=DATEADD(HOUR,@int_interval,@date_begin) set @var_SQL=@var_SQL+' union all '+' select count(*) as Sumcount,'''+CONVERT(varchar, @date_begin,120)+''' as StartTime,'''+Convert(varchar,@date_temptime,120)+''' as EndTime from applog where applog.EventTime> '''+CONVERT(varchar, @date_begin,120) set @date_begin=@date_temptime set @var_SQL=@var_SQL+ ''' and applog.EventTime <='''+CONVERT(varchar, @date_begin ,120)+''' and applog.ProjectName= '''+@var_projectName+''' ' set @int_datecal=@int_datecal-1 end end exec( @var_SQL)--Exexute the sql
事实证明我的想法是对的,执行同样的查询得到相同的结果SQL Server只需要1.319秒,性能提升了98.82%.如下图所示:
通过这次成功的优化,我发现做写程序做项目不仅仅是把项目完成就OK了。旧项目里面还有很多东西需要考虑和优化,只有不断的优化才能使项目运行的更稳定才能使自己得到更大的提升,这就是“温故而知新”的重要意义吧。
相关文章推荐
- 【原创】项目性能优化全纪录(二) 把ViewState放在服务器端
- C# 如何通过拼接XML调用存储过程来优化系统性能
- 手淘双十一性能优化项目揭秘
- 简述项目中优化sql语句执行效率的方法,从哪些方面,sql语句性能如何分析?
- (部分原创)unity项目开发中VR工程的优化(上)
- 使用Adobe Scout性能分析工具优化flash项目
- 【java】itoo项目实战之hibernate 懒载入优化性能
- 项目性能优化——SQL调优(1)
- [原创]浅谈H5页面性能优化方法
- 大数据Spark“蘑菇云”项目实战第63课: 广告点击系统高可用性和性能优化 checkpoint wal driver高可用 并行度配置
- 【原创】MySQL介绍和性能优化 (PPT/PDF)
- 技巧和诀窍;在VS 2005里优化ASP.NET 2.0Web项目的Build性能
- 简述项目中优化sql的方法,从哪些方面,sql语句性能如何分析?
- web项目性能优化(整理)
- J2EE应用性能问题的常用优化项目
- SqlServer存储过程性能效率的优化方法
- XCel 项目总结 - Electron 与 Vue 的性能优化
- Tair LDB基于Prefixkey找到如何提取一系列性能优化项目key的prefix_size
- Android性能优化之使用SparseArray代替HashMap 2013 年 08 月 01 日 android 最近在重构one的项目,其中用HashMap来缓存ActivityGroup加载
- Web项目性能优化之减少HTTP请求次数优化