zoukankan      html  css  js  c++  java
  • SQL Server 优化---为什么索引视图(物化视图)需要with(noexpand)强制查询提示

    本文出处:http://www.cnblogs.com/wy123/p/6694933.html 

     

    第一次通过索引视图优化SQL语句,以及遇到的一些问题,记录一下。

    语句分析

    最近开发递交过来一个查询统计的SQL,说是性能有问题,原本执行需要4-5秒钟,这个业务本身对性能要求又比较critical,期望是在1s之内
    在用尽各种办法之后(执行计划,统计信息,索引,改写SQL,临时表拆分),依然没有实质性的改观,
    在观察SQL本身的特点之后,
    有以下几个特点
      1,查询语句整体为多表join,但是每个表自身的数据并不是非常大,百万级
      2,查询结果在主表上一个较大的时间范围的数据进行Count的聚合操作
      3,几张表之间除了连接条件,主要是进行了一些比较复杂的逻辑运算(下面截图可以看到,没多少IO,CPU时间却很高)
        不过表的连接方式都是inner join,主要性能点就在于表关联之间的Hash join之间的逻辑运算,参考下图(是执行计划的一部分)

      通过统计信息发现,该SQL语句的物理IO并不高,说明索引没有什么问题,通过索引改善IO可能改善空间很有限
      时间主要花费在SQL语句的编译和的Hash join 运算
      尝试改写借助SQL之后(纯改写SQL和借助临时表拆分语句),发现依然很难绕过Hash join,主要是表之间的逻辑运算最为耗时
      最后想到可以先将运算好的的数据物理存储起来,然后改写查询的SQL语句完成等价的查询,
      避免每次查询都做复杂的逻辑运算,应该可以有比较大的改善,于是就想到了索引视图

      

    创建索引视图改写SQL

      在提取出来原始的查询SQL,创建索引视图,并在索引视图上创建unique cluster index和合理的nocluster index
      通过索引视图改写原始的查询统计SQL语句,
      改写后的SQL语句是一个索引视图替代原始的4张表,与另外一个物理表join,发现效率上没有任何改善,
      观察改写后的SQL语句的执行计划,发现跟原始SQL一样,并没有走索引视图上的索引,或者说是用到索引视图,一时间觉得好心塞,实在没招了
      执行计划依旧是长长的一大段,然后依旧是好几个Hash Join.参考下图,执行计划跟本文第一个截图一模一样

      按道理,索引视图固化结果集,并且根据情况做了过滤,结果集是原始查询的一部分而已,
      用同样的查询条件从索引视图做查询统计,走索引视图代价肯定要比原始SQL低,通过强制不展开with(noexpand)提示,证实了这个推断
      如下是强制不展开索引视图的统计信息,可以看到完全达到了预期的1S之内

      

      当然索引视图也不是没有代价,在一定程度上牺牲了数据写入的效率和冗余存储,来换取查询的效率
      之前简单介绍过索引视图的一些特点 http://www.cnblogs.com/wy123/p/6041122.html

    索引视图被展开(expand)的原因分析

      最关键的问题在于,没有强制不展开索引视图(with(noexpand)提示)的情况下,为什么没有走索引视图呢?

      这个问题确实郁闷了一阵子,整个半天都在想这个问题,因为索引视图本身用的就少,出现此问题更是一头雾水,不过Google一下,还有一大把类似的问题
      如下是在google的时候查到的,原文是英文,大概意思如下,非直译。

      参考链接:http://dba.stackexchange.com/questions/26979/what-factors-go-into-an-indexed-views-clustered-index-being-selected/27039#27039

    索引视图的匹配(查询用索引视图替代而不走原始的基础表)是一个相当昂贵的操作,因此优化器试图通过其他方式快速转换(生成执行计划)
    如果优化器产生了一个相对优化的执行计划,就可以尽早结束(不必继续生成其他执行计划)
    问题就在于:继续生成其他执行计划的代价要大于已生成的执行计划的代价
    听起来有点别扭,
    之前举过这么一个例子,比如说是花3秒钟找到一个相对优化的执行计划,这个执行计划完成SQL的执行需要2秒钟
    与花10秒钟的时候找到一个最优化的执行计划,尽管这个执行计划完成SQL的执行可能只需要0.5秒钟,虽然后者的执行计划更优,但整体代价更大
    优化器的主要目标是尽快找到一个足够好的执行计划(而非总是生成最好的执行计划)

    使用索引视图本身并不是一个昂贵的操作,
    但是与潜在索引视图中匹配逻辑查询树确实一个代价较大的行为,在查询涉及的视图在优化器优化之前已经被展开
    因此优化器并不知道你的查询是否未被了索引视图,他看到的只是展开的查询树
    这个通俗地讲就是:
    让sqlserver知道,一个查询,可以用索引视图中的结果等价替代视图逻辑中原始的基表,是一个代价较大的过程
    因为SQL Server根据原始的基础表,生成一种执行计划之后,就不去判断是否可以用索引视图做等价替代。

       当然白皮书里有更详细的介绍,里面索引视图相关的一些逻辑实现和分析http://www.cs.cmu.edu/~natassa/courses/15-823/current/papers/vldb00.pdf

    最后多逼逼一句:
      上面的白皮书实在看不懂,只是Google出来说详细信息请看这个参考资料,
      这里只是从现象去推断优化器在面对索引视图的一些特性,了解到内在机制的一些特点,可能潜在的问题,以及对应的解决办法
      这里又提开源软件了,别说不开源了,即便是开源了,除了钱的因素,在技术上,有几个人可以动一下这些大型软件的核心代码?
      我并不是在黑开源软件啊,只是听有人说,开源好啊,有源码怎么怎么样,觉得够装13的,
      国内除了bat等少数几家公司做过修改源码,做过开源数据库的定制,试问还有多少家可以修改数据库源码然后上生产使用

      最近在学MySQL,继续SQL Server下去恐怕踏马要失业了,开源,对大多数公司来说,钱才是一个大头因素吧,尼玛跑题了。

       

  • 相关阅读:
    delphi7在windows server 2003企业版上不能打开项目的选项(Options)窗口的解决方法
    简单的两个字“谢谢”,会让我坚持我的写作,我也要谢谢你们
    F41GUT 安装Windows server 2003系统后无法安装显卡驱动的解决办法
    远程桌面无法登录windows server 2003服务器
    F41GUT 安装Windows server 2003系统后无法安装显卡驱动的解决办法
    MS SQL Server 2000版在windows server 2003企业版系统上运行时造成数据库suspect的解决方法
    delphi7在windows server 2003企业版上不能打开项目的选项(Options)窗口的解决方法
    远程桌面无法登录windows server 2003服务器
    MS SQL Server 2000版在windows server 2003企业版系统上运行时造成数据库suspect的解决方法
    关于ajax 和josn
  • 原文地址:https://www.cnblogs.com/wy123/p/6694933.html
Copyright © 2011-2022 走看看