本文出处: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. python类型强转&二级容器

    Number 类型强转 int :         ---->>>   float,  bool,  complex,  str Float :        ---->> ...

  2. remmina从linux远程桌面连接windows失败解决方法

    删除如下文件,重新连接 rm ~/.freerdp/known_hosts

  3. ElasticSearch索引

    简介 索引是具有相同结构的文档集合.在Elasticsearch中索引是个非常重要的内容,对Elasticsearch的大部分操作都是基于索引来完成的.同时索引可以类比关系型数据库Mysql中的数据库 ...

  4. CS229 6.7 Neurons Networks whitening

    PCA的过程结束后,还有一个与之相关的预处理步骤,白化(whitening) 对于输入数据之间有很强的相关性,所以用于训练数据是有很大冗余的,白化的作用就是降低输入数据的冗余,通过白化可以达到(1)降 ...

  5. Centos7基于容器安装运行Docker私有仓库及添加认证

    一.前言 官方的Docker hub是一个用于管理公共镜像的好地方,我们可以在上面找到我们想要的镜像,也可以把我们自己的镜像推送上去.但是,有时候,我们的使用场景需要我们拥有一个私有的镜像仓库用于管理 ...

  6. Win10还原被Windows Defender隔离的文件

    Win10最新版本的Windows Defender隔离/删除的文件没有还原的选项,导致很多破解文件或是注册机直接隔离,到威胁历史记录中去却无法恢复.经过各个尝试,到微软官方论坛中也尝试了很多方法,后 ...

  7. Python网络爬虫相关基础概念

    什么是爬虫 爬虫就是通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程. 哪些语言可以实现爬虫    1.php:可以实现爬虫.php被号称是全世界最优美的语言(当然是其自己号称的,就是王婆 ...

  8. C# ORM修改实体层

    实体层:[数据库中是么以偶Contents2这个字段的],之所以在实体层添加一个Contents2,是因为: 所以在添加之后: 返回json形式,就用Contents,后台添加就用Contents2. ...

  9. QT编写TCP的问题

    ---->>>TCP编写实战的小项目 TCP套接字:主机(IP+端口) 和 服务器(IP+端口) 进行通讯,需要中间的一个锁套进行  啮合,这个锁套就是套接字的作用. 其中套接字的使 ...

  10. linux 下的常用操作命令

    一,Linux的介绍 略. 二,文件类的常用命令 三,权限类的常用命令