本文出处: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下去恐怕踏马要失业了,开源,对大多数公司来说,钱才是一个大头因素吧,尼玛跑题了。

  

SQL Server 优化---为什么索引视图(物化视图)需要with(noexpand)强制查询提示的更多相关文章

  1. Sql Server优化之索引提示----我们为什么需要查询提示,Sql Server默认情况下优化策略选择的不足

    环境: Sql Server2012 SP3企业版,Windows Server2008 标准版 问题由来: 最近在做DB优化的时候,发现一个存储过程有非常严重的性能问题, 由于整个SP整体逻辑是一个 ...

  2. SQL Server 调优系列玩转篇一(如何利用查询提示(Hint)引导语句运行)

    前言 前面几篇我们分析了关于SQL Server关于性能调优的一系列内容,我把它分为两个模块. 第一个模块注重基础内容的掌握,共分7篇文章完成,内容涵盖一系列基础运算算法,详细分析了如何查看执行计划. ...

  3. SQL Server 2000 ——系统表和系统视图

    一.系统表 数据字典的详细信息请查SQL SERVER BOL,这里仅列出一部分. 1.1.sysservers 1.查看所有本地服务器及链接服务器 select * from master..sys ...

  4. SQL Server基础之索引

     索引用于快速找出在某个列中有某一特定值的行,不使用索引,数据库必须从第一条记录开始读完整个表,直到找出相关的行.表越大,查询数据所花费的时间越多,如果表中查询的列有一个索引,数据库能快速到达一个位置 ...

  5. 转载: SQL Server中的索引

    http://www.blogjava.net/wangdetian168/archive/2011/03/07/347192.html 1 SQL Server中的索引 索引是与表或视图关联的磁盘上 ...

  6. [SQL Server优化]善用系统监视器,确定系统瓶颈

    原文:[SQL Server优化]善用系统监视器,确定系统瓶颈 来自: http://hi.baidu.com/solorez/blog/item/f82038fa0e71b78d9e51468c.h ...

  7. 深入SQL Server优化【推荐】

    深入sql server优化,MSSQL优化,T-SQL优化,查询优化 十步优化SQL Server 中的数据访问故事开篇:你和你的团队经过不懈努力,终于使网站成功上线,刚开始时,注册用户较少,网站性 ...

  8. SQL Server优化的方法

    SQL Server优化的方法<一>   查询速度慢的原因很多,常见如下几种:   1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)   2.I/O吞吐量小,形成了 ...

  9. Sql Server优化之路

    本文只限coder级别层次上对Sql Server的优化处理简结,为防止专业DB人士有恶心.反胃等现象,请提前关闭此页面. 首先得有一个测试库,使用数据生成计划生成测试数据库(参考:http://de ...

随机推荐

  1. windows 日志解决方法

    1.sql server 2012 报错 MSSQLSERVER 服务无法使用当前配置的密码以 .\MSSQL_SF_A9JGSK 身份登录,错误原因如下: 此帐户的密码已过期. 要确保服务配置正确, ...

  2. 转:JavaScript Reference for Microsoft Dynamics CRM 2011 / 2013

    JavaScript Reference for Microsoft Dynamics CRM 2011 / 2013 98 Replies Here’s a quick reference guid ...

  3. mysql连接状态

    mysql连接状态 mysqladmin -uroot -h127.0.0.1 status mysqladmin -uroot -h127.0.0.1 processlist

  4. Maven中-DskipTests和-Dmaven.test.skip=true的区别

    在使用mvn package进行编译.打包时,Maven会执行src/test/java中的JUnit测试用例,有时为了跳过测试,会使用参数-DskipTests和-Dmaven.test.skip= ...

  5. JS+Ajax+Servlet:记录页面访问时间

    1.前端JS记录页面访问时间 1.1JQuery版本: <script type="text/javascript" src="js/jquery.min.js&q ...

  6. 安全测试5_服务端的安全漏洞(SQL注入、命令注入、文件操作类)

    前面大致讲解了下客户端的安全漏洞,现在来讲解下服务端的安全漏洞. 1.SQL注入(SQL Injection),是一种常见的Web安全漏洞,攻击者利用这个漏洞,可以访问或修改数据,或者利用潜在的数据库 ...

  7. alias with parameter,linux

    alias demoAlias1='_(){ git checkout -b $1; command2;}; _'

  8. django之前-----web应用与框架

    一web应用 web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件.应用程序有两种模式C/S.B/S. 下面来看一个简 ...

  9. Linux中设置vi编辑器的编码格式以及使用

    vi ~/.vimrc set fileencodings=utf-8,gbk set termencoding=utf-8 set encoding=utf-8 vim的多行移动 一.连续的十几行到 ...

  10. android 开发 实现RecyclerView的列表单选功能

    实现思维: 1.首先在一行的xml布局中添加一个选中效果的icon图片,未选中的情况下INVISIBLE或者GONE 都可以,推荐使用INVISIBLE它会占用布局位置但是不显示,这样可以避免布局中其 ...