当前位置:首页 > 开发 > 数据库 > 正文

产品详情页面加载慢(之前约7s-12s)

发表于: 2013-04-27   作者:BenjaminYu   来源:转载   浏览次数:
摘要: 问题场景:客户反应网站上的产品详情页面打开时,速度很慢。 运行环境:   数据库服务器 32位SQL Server 2005 开发者版SP2 开启了AWE   应用服务器 JDK 1.6,Tomcat 6.0 解决步骤:   1.火狐,Firebug>网络 查看打开该页面后的时间线 确实是数据查询耗时长导致页面加载慢。   2.懒得拉代码配
问题场景:客户反应网站上的产品详情页面打开时,速度很慢。
运行环境:
  数据库服务器 32位SQL Server 2005 开发者版SP2 开启了AWE
  应用服务器 JDK 1.6,Tomcat 6.0
解决步骤:
  1.火狐,Firebug>网络 查看打开该页面后的时间线 确实是数据查询耗时长导致页面加载慢。
  2.懒得拉代码配置测试环境了(这个项目不能实行热部署,改了程序不能直接看到效果,不太爽),直接在客户机器上通过SQL Server Profiler创建跟踪来获取耗时长的查询。跟踪时间只是点开产品详情页面前后大约15s,这段时间内有一条查询的CPU、IO占用都高的离谱,所以很容易就确定了就是这条慢查询导致的页面打开慢。通过报表看,这条查询平均占用CPU时间8s多,已经执行2W多次。。。。。
  3.将查询拷到Management Studio,添加参数值,设置统计io和time开关,开启实际执行计划,执行查询,分析结果。定位到union前后的两段查询条件重复,导致对连接的另一张大表逻辑读达到40W+,于是改写查询条件,时间缩短为0.15s左右。
  4.提交开发的同事修改,问题解决。

后记:
开发的同事修改之后,速度并无明显改善,于是乎,重来步骤2,发现当product_status字段(varchar类型)的值为'50'时,查询的代价要明显高于传入值为50的情况。这个很费解。。
上执行计划(计划中不同的部分)
Sort(TOP 1, ORDER BY:([t].[dbgndate] ASC))
 |--Filter(WHERE:(CONVERT_IMPLICIT(int,[db].[dbo].[product_info].[product_status] as [t].[product_status],0)=(50) AND CONVERT(varchar(100),[db].[dbo].[product_info].[dbgndate] as [t].[dbgndate],23)>=CONVERT(varchar(100),getdate(),23) AND ([db].[dbo].[product_info].[product_issue] as [t].[product_issue]='2' OR [db].[dbo].[product_info].[product_issue] as [t].[product_issue]='3')))
 |--Nested Loops(Inner Join, OUTER REFERENCES:([t].[uid]))
 |--Index Seek(OBJECT:([db].[dbo].[product_info].[ix_t_product_ulineid] AS [t]), 
 	SEEK:(
	  [t].[ulineid]
	  =[db].[dbo].[t_line].[uid] as [tl].[uid]
	) ORDERED FORWARD)

对product_info逻辑读5W次

Top(TOP EXPRESSION:((1)))
 |--Filter(WHERE:([db].[dbo].[product_info].[product_issue] as [t].[product_issue]='2' OR [db].[dbo].[product_info].[product_issue] as [t].[product_issue]='3'))
 |--Nested Loops(Inner Join, OUTER REFERENCES:([t].[uid]))
 |--Index Seek(OBJECT:([db].[dbo].[product_info].[ix_product_info_status_dbgndate] AS [t]), 
 	SEEK:(
	  [t].[cstatus]='50'), 
	  WHERE:([db].[dbo].[product_info].[ulineid] as [t].[ulineid]
	 	=[db].[dbo].[t_line].[uid] as [tl].[uid] 
	  AND CONVERT(varchar(100),[db].[dbo].[product_info].[dbgndate] as [t].[dbgndate],23)
	  >=CONVERT(varchar(100),getdate(),23)
	) ORDERED FORWARD)

对product_info逻辑读124W次

详细的不说了(现在我也说不清,只能感觉到要调整索引),上解决方案:
新增索引
create index ix_product_info_ulineid_status_dbgndate  on product_info(ulineid, product_status, dbgndate) include(product_issue, uid);


上新增索引后的执行计划:
   |--Nested Loops(Inner Join, OUTER REFERENCES:([tl].[uid], [Expr1038]) WITH ORDERED PREFETCH)
        |--Sort(ORDER BY:([tl].[dupdate] DESC))
        |    |--Index Seek(OBJECT:([db].[dbo].[t_line].[ix_t_line_cstatus_cissue] AS [tl]), SEEK:([tl].[cstatus]='50' AND [tl].[cissue]='2' OR [tl].[cstatus]='50' AND [tl].[cissue]='3') ORDERED FORWARD)
        |--Top(TOP EXPRESSION:((1)))
             |--Index Seek(OBJECT:([db].[dbo].[product_info].[ix_t_product_info_ulineid_cstatus_dbgndate] AS [t]), SEEK:([t].[ulineid]=[db].[dbo].[t_line].[uid] as [tl].[uid] AND [t].[product_status]='50'),  WHERE:(CONVERT(varchar(100),[db].[dbo].[product_info].[dbgndate] as [t].[dbgndate],23)>=CONVERT(varchar(100),getdate(),23) AND ([db].[dbo].[product_info].[product_issue] as [t].[product_issue]='2' OR [db].[dbo].[product_info].[product_issue] as [t].[product_issue]='3')) ORDERED FORWARD)
                 |         |    |    |--Clustered Index Seek(OBJECT:([db].[dbo].[product_info].[pk_y_product_info_uid] AS [tt]), SEEK:([tt].[uid]=[db].[dbo].[product_info].[uid] as [t].[uid]) ORDERED FORWARD)

对product_info逻辑读降为7K,CPU占用时间约为100ms
对比最初的开销,性能提升非常大,刚开始看执行计划,脑袋晕了,优化就暂时先做到这一步。

产品详情页面加载慢(之前约7s-12s)

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
学习j2se,马士兵老师讲内存分析是如此的透彻,遇到这么精华的东西,让我不得不再写篇感悟博客以作
问题描述: 最近同事使用ECSHOP v273帮客户开发了一个商城系统,部署到服务器在测试的时候发现 产品
jQuery 页面载入进度条 Shawn Published@17:40 / 2009-01-07 / Trackback / Skip 页面 Loading 条基
  window.onload=function(){...}作用是当页面加载的时候可以调用某些函数,例如: window.onload
本周开始做一个新的管理平台。 前台构建为了开发效率,直接采用dwz,国产,文档也是中文。 已经使用d
作为刚实习半年的菜鸟来说,一直以来都觉得在五花八门的软件行业必须要有自己的立场,我一直坚持将
先看看效果: 1 aspx: Code <%@ Page Language="C#" AutoEventWireup<span style="color: #00
以安装模块installation/index.php的加载过程为例,整个加载过程分为3部分: 0. index.php 1. 预加
不知道各位小伙伴在做前端页面的时候,会不会跟我有一样的经历,整个系统大体上是需要一个整体框架
Spring Junit 单元测试 在bean初始化前设置系统属性 背景: 已有代码,有些工厂类通过System.getPrope
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号