今天在做一个统计功能时,写了一个存储过程,该存储过程就是接受两个日期型参数,返回一个统计后的数据集,在存储过程中使用了两个表的联合查询,写完后,用exec运行了下,速度很慢,经过调查后,我把其中一个表中的GUID列加了一个聚集索引,然后针对这个表重建了下索引,然后再用exec跑了下该存储过程,结果快多了,一秒钟即可,以前的话需要17秒,后来我发现逻辑不对,就又在where子句后加了一个条件,然后再用exec跑了下该存储过程,结果又需要17秒钟了,然后我就又针对该表重建了下索引(使用DBCC),然后再用exec跑了下该存储过程,结果1秒钟就出来了,然后我又改了下where子句,结果跑一次又需要17秒钟了,然后重建索引又好了现在就是感觉只要动一下那个存储过程的where子句,哪怕是在后面加一个 " and 1=1",然后跑起来就N慢,需要17秒,必须得重建索引才行,索引重建后跑一次只需要1秒请问哪位有数据库优化经验的高手能给个说法这是为什么吗,给个参考也行 谢谢

解决方案 »

  1.   

    每次改WHERE 不一样么?
    你改了语句当然要重新编译啦.(很大可能)
      

  2.   

    在后面为什么要加一个 " and 1=1"?
    where 后面尽量将主键、聚簇索引、非聚簇索引放在左边,一旦将 1=1 放在了最左边,索引将不会起作用的
      

  3.   

    我并不是非要加一个" and 1=1",我的意思是指,在开发过程调试中难免会改动这个where语句,难道每次改动where语句后哪怕很简单的改动,都要重建这个表的索引才能达到和改动前相当的效率吗例如:
    改动前:select xxx from mmmm where WorkInsGUID='F9E01CD7-6E62-42B7-9423-6D9067D75736',重建索引后 查询效率:1秒
    然后改成:select xxx from mmmm where WorkInsGUID='F9E01CD7-6E62-42B7-9423-6D9067D75736' and 1=1 查询效率:17秒,必须重建mmmm表的索引后,查询效率又恢复到1秒这是为什么呢,我仅仅只是加了一个"1=1"的查询条件啊,根本就没动mmmm表的索引啊
      

  4.   

    1.GUID加聚集索引是不明智的选择.索引碎片太容易产生了.--把聚集索引去掉吧.
    2.你动态拼接WHERE 是传参数进去的还是里面去写好的?如果你没弄好.可能重新编译.或者重新使用执行计划不准确.
      

  5.   

    1.去掉这个聚集索引后,查询永远很慢,我们是二期项目,里面有用户的真实数据,数据库的设计就只能这个样了,所以guid字段也不能改成int类型的
    2.where的条件是传参数进去的
      

  6.   

    1GUID列可以改用唯一非聚集索引.(因为你要传入GUID.(最好加另一列为聚集),能满足你的性能)
    2我问的意思是 AND 1=1 是你直接传进去的?
      

  7.   

    关于第2点 我再说一下,准确的说,我是通过传参数调用存储过程,存储过程中把接受到的参数值拼接到一个sql字符串中,然后使用exec(@strSql)这样去运行这个动态的sql语句从而返回这个动态sql语句的查询结果
      

  8.   


    and 1=1 是我在动态sql里写死的
      

  9.   

    嗯 我建了个唯一非聚集索引,效果不错,不过每次修改后还是要重建索引,不过这个问题我大概也明白了,可能和动态sql执行计划的选择有关系,执行计划没有重用,待我有时间好好研究下,谢谢SQL77这位高手的提醒和建议
      

  10.   

    将动态sql改为静态sql,还是采用传递参数调用存储过程,该问题成功解决