我写的视图很烂,还请大侠们费心看看。SELECT     dbo.Today.Task AS TaskDescr, dbo.Today.No, dbo.Today.Downno, 
                      dbo.Today_2.time4 AS time4, dbo.Today.Via AS bypass, dbo.Today.Hos AS Hos, 
                      dbo.Today.time1 AS time1, dbo.Today.time2 AS time2, 
                      dbo.Today.time5 AS Time5, dbo.Today.time3 AS time3, 
                      dbo.Today.Area AS area, '出' AS io, dbo.Today.Status, 
                      CASE WHEN dbo.Today.ber < 0 THEN '' WHEN dbo.Today.ber IN (1) THEN '南' + CONVERT(varchar, 
                      dbo.Today.ber) WHEN dbo.Today.ber > 17 THEN '北' + CONVERT(varchar, dbo.Today.ber) 
                      ELSE CONVERT(varchar, dbo.Today.ber) END AS Ber, dbo.Today.Gate AS Gate, 
                      dbo.Today.Pla AS Pla, dbo.Today.type,  
                      dbo.Reason.ReasonCN AS DisplayReason, CASE WHEN ltrim(rtrim(dbo.Today.Memo)) = '' AND 
                      ltrim(rtrim(dbo.Today.StatMemo)) <> '' THEN dbo.TodayD.StatMemo WHEN ltrim(rtrim(dbo.Today.Memo)) 
                      <> '' AND ltrim(rtrim(dbo.Today.StatMemo)) 
                      = '' THEN dbo.Today.Memo WHEN ltrim(rtrim(dbo.Todays.Memo)) <> '' AND 
                      ltrim(rtrim(dbo.Today.StatMemo)) 
                      <> '' THEN dbo.Today.Memo + ',' + dbo.Today.StatMemo WHEN ltrim(rtrim(dbo.Today.Memo)) = '' AND
                       ltrim(rtrim(dbo.Today.StatMemo)) = '' THEN '' END AS Re, ISNULL(dbo.f_MergeVipName(dbo.Today.No, 
                      N'出', dbo.Today.Opday), N'') AS vipinfo, dbo.Today.lines
FROM         dbo.Today LEFT OUTER JOIN
                      dbo.Reason ON dbo.Today.PublishReason = dbo.Reason.ReasonID LEFT OUTER JOIN
                      dbo.Today_2 ON dbo.Today.Downno = dbo.Today_2.no
WHERE     (dbo.Today.Task NOT IN ('货A', '货B'))这里的dbo.Today和dbo.Today_2都分别只有100多条的记录。字段也差不多都是35个。dbo.Reason里面是31条记录,6个字段。dbo.f_MergeVipName,这个函数如下:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
goALTER function [dbo].[f_MergeVipName](@no nvarchar(20),@Io nvarchar(20),@Opday Datetime)
returns nvarchar(Max)
as
begin
declare @r nvarchar(Max)
set @r=''select @r=@r+';'+( Name+','+ Class) from Vip where no=@no and Io = @Io and [Date]=@opdayreturn stuff(@r,1,1,'')
end会不会是视图里面的memo判断导致的?还是这个dbo.f_MergeVipName函数导致的?
若是函数导致的,我测试了select Name+','+ Class as test from Vip where no like '%%' and Io = '出' and [Date]='2013-07-25',执行时间是0秒。
这个VIP表里有2万1千条记录,但是每天的记录也就10几条,很少的。是在客户端用SQL SERVER 2005连接到服务器上,用select * from view去执行的视图,这是最新刚刚执行的,执行了10次,花费时间如下,单位为秒。
5,5,5,2,4,3,3,3,3,2
去掉dbo.f_MergeVipName,这个函数以后,貌似会快1秒左右。但是去掉的话,也不是个办法啊,客户要看啊。除非把该表改一改,只提供当天的,历史的每天自动保存到专门的历史表里了。服务器配置如下,比较低端啊:IBM X3550M2  机架式服务器(至强四核E5504一个 4G内存 146GB热插拔SAS硬盘)
一般情况下是100多个客户端,高峰时可能有200以上,客户端程序30秒刷新一次该视图。
跪求各路大侠分析一下,变慢的可能的原因在哪里呢?

解决方案 »

  1.   

    1 看看硬件瓶颈。 数据库服务器很吃资源的。 你的内存4GB稍微不足。 2 看看你的iddex 可能你数据量多了,所以速度变慢了。3 优化一下你的sql script.看的出来有不少要优化的哈     
      

  2.   


    iddex是什么?我不懂啊,能说详细点吗?要优化哪些?能详细说说吗?
      

  3.   

    --today, reason, today_2数据量很少,全表扫描没有问题
    --Vip表加索引: [Date],[No],[io] INCLUDE(NAME)
    --如果还不行
    SET STATISTICS IO, TIME ON
    查看实际的执行计划,分析一下
      

  4.   


    iddex是什么?我不懂啊,能说详细点吗?要优化哪些?能详细说说吗?INDEX 
      

  5.   

    是执行这句是吗?
    create index  test_vip_idx on vip([Date],[No],[io])  INCLUDE(NAME)
    能不能解释一下include,我百度了一下,不是很理解,而且为什么Class字段又不要include呢?
      

  6.   

    index 就是创建另外一个表,按照一定顺序来排列你的index的column.当运行时,系统会先到你的index表里去寻找符合的值。然后根据index表里的地址,去找你实际的row. include就是在你的index里包含一些column, 然后如果你的index表里已经有了你所需要的数据,那么你是不是省了下一步了。那么这么做就提高了搜索的效率。  
      

  7.   

    SORRY,应该是:
    create index  test_vip_idx on vip([Date],[No],[io])  INCLUDE(NAME,CLASS)
    你可以把非聚集索引理解成是,另外一张表,与原来的数据表没有关系。唯一的关系是在索引的每行记录最后,存储了一个rowid字段,指向原来的数据表的相应记录。
    想了解INCLUDE,得首先知道索引的存储结构。不管是聚集还是非聚集索引,都是平衡树结构。
    没有INCLUDE的非聚集索引,叶子结点只包含索引键([Date],[No],[io]);
    有INCLUDE的非聚集索引,除了索引键,还包含了另外的数据(NAME,CLASS);
    当索引查找时,只会根据索引键查找,当查找到需要的数据后,就可以从INCLUDE的数据中直接取出想要的数据;否则,还要再去和数据表关联,从中取出NAME,CLASS字段。
      

  8.   

    谢谢各路大侠。最终是新建了个VIP历史表,把2013年之前的记录转移到历史表里去。目前VIP表记录数为2100条左右。计划今后每半年或一年转移一次。相关的查询历史的代码要做些修改。