设为首页 收藏本站
查看: 1128|回复: 0

[经验分享] 程序员眼中的 SQL Server-执行计划教会我如何创建索引?

[复制链接]

尚未签到

发表于 2015-6-27 05:48:41 | 显示全部楼层 |阅读模式
先说点废话
  以前有 DBA 在身边的时候,从来不曾考虑过数据库性能的问题,但是,当一个应用程序从头到脚都由自己完成,而且数据库面对的是接近百万的数据,看着一个页面加载速度像乌龟一样,自己心里真是有种挫败感。代码的优化问题,这是属于程序员的职责范围之内,对于我来说,这一方面比较好探查些,因为都是自己熟悉的,用 EF 或 SQL Server Profiler 跟踪一下程序代码产生的 SQL,如果有问题,直接优化程序代码就可以了,如果 SQL 没问题,那就得优化数据库了,对于我来说,这是一个无人区。
  前两天,自己瞎搞了一个测试:程序员眼中的 SQL Server-非聚集索引能给我们带来什么?,因为对索引不是很熟悉,所以测试得到结果没有任何价值,甚至有些误导人,这边说声抱歉,在哪跌倒在哪爬起来。

应用场景
  还是用商品表(Product)作为示例,表结构如下:
DSC0000.png
  存在这样一种业务场景:获取某个供应商(ProviderID),状态为已售(State 为 1)的商品列表,排序方式为生产日期(ProduceTime)降序,有可能我们应用程序在显示数据的时候用到分页,这边我们查询前 100 行。翻译为 SQL 代码:
  

SELECT TOP 100  
[ID],
  
[Name],
  
[Remarks],
  
[ProviderID],
  
[ProduceTime],
  
[State]
  
FROM [TestDB].[dbo].[Product]
  
WHERE [ProviderID]=1 AND [State]=1
  
ORDER BY [ProduceTime] DESC
  

  上面这个业务场景,在我们一般的应用程序中基本上都会遇到,有时候数据量不是很大的时候,我们一般不会做任何数据库优化,但是你看了下面的实践,你是否应该考虑下,为你现在的数据库加个索引呢?

SQL Server 执行计划
DSC0001.png
  SQL Server 执行计划,是我们分析 SQL 执行情况的一大利器,通过它,我们也可以很方面的查看索引的执行,在实践之前,需要了解一些必备技能,以下知识点摘自-看懂 SqlServer 查询计划。
  SQL Server 有二种索引:聚集索引和非聚集索引。二者的差别在于:【聚集索引】直接决定了记录的存放位置, 或者说:根据聚集索引可以直接获取到记录。【非聚集索引】保存了二个信息:1.相应索引字段的值,2.记录对应聚集索引的位置(如果表没有聚集索引则保存记录指针)。 因此,如果能通过【聚集索引】来查找记录,显然也是最快的。
  SQL Server 会有以下方法来查找您需要的数据记录:


  • 【Table Scan】:遍历整个表,查找所有匹配的记录行。这个操作将会一行一行的检查,当然,效率也是最差的。  

  • 【Index Scan】:根据索引,从表中过滤出来一部分记录,再查找所有匹配的记录行,显然比第一种方式的查找范围要小,因此比【Table Scan】要快。  

  • 【Index Seek】:根据索引,定位(获取)记录的存放位置,然后取得记录,因此,比起前二种方式会更快。  

  • 【Clustered Index Scan】:和【Table Scan】一样。注意:不要以为这里有个Index,就认为不一样了。 其实它的意思是说:按聚集索引来逐行扫描每一行记录,因为记录就是按聚集索引来顺序存放的。 而【Table Scan】只是说:要扫描的表没有聚集索引而已,因此这二个操作本质上也是一样的。  

  • 【Clustered Index Seek】:直接根据聚集索引获取记录,最快!
  所以,当发现某个查询比较慢时,可以首先检查哪些操作的成本比较高,再看看那些操作在查找记录时, 是不是【Table Scan】或者【Clustered Index Scan】,如果确实和这二种操作类型有关,则要考虑增加索引来解决了。 不过,增加索引后,也会影响数据表的修改动作,因为修改数据表时,要更新相应字段的索引。所以索引过多,也会影响性能。 还有一种情况是不适合增加索引的:某个字段用0或1表示的状态。例如可能有绝大多数是1,那么此时加索引根本就没有意义。 这时只能考虑为0或者1这二种情况分开来保存了,分表或者分区都是不错的选择。

应用分析

  我们先不建任何索引(除了主键> DSC0002.png

  可以看到,查询开销基本上被 SORT 霸占了,看到这种情况,按照正常的思维,我们首先考虑的是为 ProduceTime 创建一个非聚集索引,然后按照 DESC 排序,但有时候我们要沉下心思考一下,是不是用> DSC0003.png

  从上面的执行计划中,我们可以很直观的看出差别,所以在写 SQL 的时候,一定要慎重啊,这边为了方便展示,我们还是以 ProduceTime 字段进行排序,按照> DSC0004.png
  创建好之后,我们再来执行一下 SQL 代码:
DSC0005.png
  “Key Lookup(Clustered)”记录,其实还是全表进行查找,默认通过聚集索引(PK_Product),我们可能会有疑问,索引就是按照查询及排序方式创建的啊,为什么还是这种情况?这时候我们看一下 SELECT 后面的字段就知道了,我们查询显示的是 Product 表中所有字段,但是 IX_Product_Provider_State 非聚集索引,只是针对的查询条件字段,并没有吧查询显示字段包含进来,在创建索引窗口中,“索引键 列” TAB 的旁边有个“包含性 列”,我们把其他显示字段加进来,看下执行效果:
DSC0006.png
  “Index Seek”,这就是我们想要的效果,其实关于索引的创建有很多的现实问题,比如组合字段索引和单个字段索引有何不同?就像上面示例中的查询用例,如果 ProduceTime 排序在其他查询条件中也存在,是不是应该拉出来创建一个索引?还是像上面一样,和查询条件一起创建一个组合字段索引?还有一种情况就是,在一个应用程序查询中,存在单个字段的查询,也存在组合字段的查询,那这时候我们是创建单个字段索引?还是创建组合字段索引呢?这几个问题,你创建一下索引,然后用“ SQL 执行计划”试试就知道了。

总结

  针对上面的查询用例,我个人觉得,最好的方案是:排序字段使用>  做完这些,你会发现,你的应用程序像飞的一样。
  ps:我要飞得更高。。。
  参考资料:


  • How to reduce clustered index scan cost by using SQL query  

  • SQL Primary key sort order  

  • Index Sort Order  

  • 请问一下order by与索引的问题  

  • 写写如果SELECT列表中,使用和不使用的索引使用情况

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-80843-1-1.html 上篇帖子: 灵活运用 SQL SERVER FOR XML PATH 下篇帖子: 人人都是 DBA(IV)SQL Server 内存管理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表