位置: 编程技术 - 正文

Sql Server 查询性能优化之走出索引的误区分析(sqlserver查询语句大全讲解)

编辑:rootadmin
据了解绝大多数开发人员对于索引的理解都是一知半解,局限于大多数日常工作没有机会、也什么没有必要去关心、了解索引,实在哪天某个查询太慢了找到查询条件建个索引就ok,哪天又有个查询慢了,再建立个索引就是,或者干脆把整个查询SQL直接发给DBA,让DBA直接帮忙优化了,所以造成的状况就是开发人员对于索引的理解、认识很局限,以下就把我个人对于索引的理解及浅薄认识和大家分享下,希望能解除一些大家的疑惑,一起走出索引的误区 误区1.在表上建立了索引,在查询时用到了索引的列,索引就一定会生效   首先明确下这样的观点是错误的,SQL Server查询优化器是基于开销进行选择的优化器,通过一系列复杂判断来决定是否使用索引、使用什么类型索引、使用那个索引。SQL Server内部维护着索引列上的数据的统计,统计信息会随着索引列内容的变化而变化,索引的有效期完全取决于索引列上的统计信息,随着数据的变化关于索引的检索机制也随之变化。对于查询优化器来说始终保持查询开销最低始终是其的不二选择,如果一个非聚集索引的列上有大量的重复值,那么这个索引就不会有什么存在的意义,这也是为什么不建议在类似性别,bit类型上面建立非聚集索引的原因。   说到这里可能会有人疑惑,我在性别列上建一个索引,性别只有两个值男、女,当我我们查询条件中有性别这个字段时最起码会过滤掉一半的数据,能大幅缩小我们需要检索的数据范围,怎么会没用呢?(事实上这也是我曾经困惑的地方),对我们理解的没错,比如说Users表性别列Gender上建立索引IX_Gender,执行select Gender from Users where Gender='男' ,这个查询效率非常高而且也成功使用了索引IX_Gender,然而我们这样写SQL的时候少之又少,更多的我们会写这样的SQL:select UserID,UserName,Phone,Email from Users where Gender='男' 这时再去看看查询计划根本没用使用索引IX_Gender,而是进行了一个聚集索引扫描或者表扫描,查询条件where Gender='男' 明明在IX_Gender里面定义了,为什么没使用呢,这一切罪恶的根源就在于书签查找(RID、键查找),好了关于书签查找不是我们要讨论的话题,在这里只想告诉大家,索引不是万能的,索引不是创建了就一定有效。 误区2.聚集索引扫描用到了聚集索引索引,所以性能很高   一般来说我们可以认为聚集索引是效率最高的索引,但聚集索引扫描绝不代表高效,本质上聚集索引扫描就是表扫描,一般出现扫描字样时代表缺少索引或者索引无效,所以我们日常应用中应该避免在查询计划中看到扫描字样,更多的出现聚集索引查找、索引查找才真正的使用到了索引,才是王道。 误区3.聚集索引扫描(表扫描)是全表扫描,所以只要出现了表扫描就一定代表性能低下   在误区2中我们说到应该尽量避免出现聚集索引扫描或者表扫描,这是我们必须要坚持的原则,但这并不代表这出现表扫描就一定性能低下,有些情况下表扫描反而比索引查找有着更高的效率(一般出现在返回数据量较大,出现大量书签查找的情况下) 误区4.查询计划中看到了键查找或者RID查找时有着很高的性能   键查找和RID查找统称为书签查找,和错误认识正好相反,出现书签查找反而代表着性能低下,有些情况下甚至有着比表扫描更低的效率,因此我们应该尽量避免书签查找。在返回数据量较小时,书签查找对性能影响不大,若返回数据量较大,书签查找会严重影响查询性能,因此我们建立索引时应该尽量覆盖要返回的所有列,当然索引列数是有限的而且也不能单纯的为了避免书签查找而在索引中包含大量的列,可以使用覆盖索引来解决书签查找问题,或者需要大数据量返回时尽量使用聚集索引;同时这也是为什么常听说的不要使用select *,而只选择需要的列进行输出,因为select *很容易导致书签查找,毕竟我们不打可能在所有列上建立索引,也不可能所有查询都使用聚集索引(使用聚集索引和表扫描时不存在书签查找) 误区5.查询开销统计中的逻辑读次数是读取的记录数   天真的我曾经也这么认为,查询计划中逻辑读次数就是读取的记录数,然而看我们的查询4.1全表扫描返回行数据,为啥逻辑读只有次,而查询4.5同样是返回行数据,逻辑读为啥次呢,一次读取一条的话逻辑读次最多返回行数据,逻辑读次的话应该返回条数据吧,有点小晕,这里解释下逻辑读次数是指读取的页面数,一个面8KB,8个页面构成一个区KB,对于我们的示例表来说个页面足以存下所有数据,所以表扫描时只需读取次就可以了,那查询4.5为啥读取了次呢,就算一个页面就一条数据按理说最多多次也可以读取完毕了,这是因为Sql Server对数据读取的最小单位就是页,哪怕读取一条数据也需要读取整页数据,而非聚集索引的读是随机读哪怕多条记录在同一页上也会导致多次重复读取,外加书签查找导致了这么多的逻辑读,这也是为什么非聚集索引不适合读取大量数据的原因之一。 我们以Northwind数据库表Orders表为示例进行下演示  1.先将Orders表的索引全部删除  4.在OrderID上面创建聚集索引,索引列为OrderID   3.在Orders表上创建非聚集索引IX_OrderDate create index IX_OrderDate on Orders(OrderDate) 4.设置查询分析器选中包含实际的执行计划(右键-->包含实际的执行计划),打开IO统计,并依次执行以下查询 4.1 执行 select * from Orders 的查询开销及查询计划    可以看到执行的聚集索引扫描,逻辑读次,没有使用索引,返回行数行    

  4.2 执行 select * from Orders where OrderDate<='-7-' 的查询开销借查询计划    可以看到成功使用了在OrderDate上面建立的索引IX_OrderDate,逻辑读次数为,返回行数6行

    4.3 执行 select * from Orders where OrderDate<='-1-1' 的查询开销及查询计划    可以看到虽然我们在OrderDate上面建立了索引IX_OrderDate,但执行计划并没有使用索引IX_OrderDate而是执行了一个聚集索引扫描,逻辑读次数而这个查询与4.2的区别仅仅在于OrderDate的值不一样,返回行数行    4.4 执行 select * from Orders with(index=IX_OrderDate) where OrderDate<='-1-1' 的查询开销及查询计划    可以看到查询条件和4.3完全一致,我们强制使用了IX_OrderDate,返回记录数和4.3完全一致,但逻辑读达到了次,返回行数行        

  4.5 执行 select * from Orders with(index=IX_OrderDate) where OrderDate<='-1-1' 查询开销及查询计划

    同样我们强制使用了索引IX_OrderDate,查询条件进行改变,逻辑读达到了次,返回行数数行    

    

查询统计查询SQL索引返回行数逻辑读次数4.1 select * from Orders聚集索引扫描.2 select * from Orders where OrderDate<='-7-'IX_OrderDate.3 select * from Orders where OrderDate<='-1-1'聚集索引扫描.4 select * from Orders with(index=IX_OrderDate) where OrderDate<='-1-1'强制使用IX_OrderDate.5 select * from Orders with(index=IX_OrderDate) where OrderDate<='-1-1'强制使用IX_OrderDate

通过对比以上查询我们可以知道虽然我们建立了索引,但索引并不总是有效,强制使用索引只会带来更低的效率,查询优化器会根据索引列的统计信息自动选择最优的查询计划进行执行。查询4.3和4.4查询条件完全一样,虽然我们建立了索引IX_OrderDate,但查询优化器并没有采用而是选择了开销更低的聚集索引扫描,在我们强制使用了索引后查询开销反而激增从逻辑读次达到了次,而我们仅仅查询到了行数据;在查询4.5中我们继续强制使用索引,改变查询条件的值,在返回行数据的情况下逻辑读次数达到了次,而返回相同数据的查询4.1仅仅执行了次逻辑读。

  困惑:通过查询4.1我们知道Orders表一共才有条数据,为什么我们在查询4.5中强制使用索引后逻辑读达到了恐怖的次呢,即便一条数据读取一次也才不过次啊。

  解惑:查询4.5强制使用索引后,查询优化器首先去到索引IX_OrderDate上面检索,然后在根据索引IX_OrderDate去找聚集索引指针,根据聚集索引指针去聚簇索引叶子节点(实际数据行)查找数据(书签查找),才导致了更大的查询开销。

  结论:    1.索引不是万能的,查询列上建立了索引不代表就一定会使用索引(参见结论2)    2.绝大多数情况下查询优化器会根据索引列上的数据统计信息自动选择最优的执行计划,而且查询计划会随着数据量变化而变化,所以如果不是有必要不要使用索引提示来强制使用某索引    3.聚集索引扫描、表扫描不代表一定低效(表扫描不存在书签查找,使用非聚集索引返回大量行时,若存在书签查找反而不如表扫描性能高)    4.索引查找不一定高效(非聚集索引查找时容易出现书签查找)    5.书签查找会降低查询效率,尤其是大范围读取数据时会严重影响效率,所以应该尽量避免书签查找或出现书签查找时尽量返回较少的数据行    6.需要注意下查询开销统计里的逻辑读是指读取的页面数而不是数据行数

 示例中采用的语句及数据仅作为演示使用,实际开发应用中要比示例的数据复杂的多,同一个查询在不同的环境下可能产生完全相反的结果,如何应用好还主要在于我们个人的认识和理解,希望有幸看到本文的朋友能借此加深一些对索引的理解和认识,走出索引的误区,开发出高性能的应用。

  本人不是DBA,只是一名普通的开发人员,以上均为实际工作中的一些经验、体会,鉴于本人水平非常有限,有说的不对或理解不到位的地方还望各位大神给予指正,以免误导他人,不胜感激。

后续会继续写一些关于Sql Server查询性能优化方面的实践经验,主要包含以下几方面Sql Server查询性能优化之建立合理的索引Sql Server查询性能优化之避免书签查找Sql Server查询性能优化之复用查询计划Sql Server查询性能优化之选择合适的字段类型 附上用的数据表:DemoDB.rar 从Northwind数据库分离出来的,仅用了其中的Orders表 此文章属懒惰的肥兔原创

推荐整理分享Sql Server 查询性能优化之走出索引的误区分析(sqlserver查询语句大全讲解),希望有所帮助,仅作参考,欢迎阅读内容。

Sql Server 查询性能优化之走出索引的误区分析(sqlserver查询语句大全讲解)

文章相关热门搜索词:sql server数据查询语句,sql Server 查询性能优化,sql Server 查询性能优化,sqlserver查询数据,sql server简单查询,sqlserver查询性能分析工具,sql Server 查询性能优化,sql Server 查询性能优化,内容如对您有帮助,希望把文章链接给更多的朋友!

SqlServer参数化查询之where in和like实现详解 身为一名小小的程序猿,在日常开发中不可以避免的要和wherein和like打交道,在大多数情况下我们传的参数不多简单做下单引号、敏感字符转义之后就

SqlServer参数化查询之where in和like实现之xml和DataTable传参介绍 方案5使用xml参数对sqlserverxml类型参数不熟悉的童鞋需要先了解下XQuery概念,这里简单提下XQuery是用来从XML文档查找和提取元素及属性的语言,简单说就

SQLServer中字符串左对齐或右对齐显示的sql语句 知识点:函数replicate以下代码是实现如下功能:declare@sqlvarchar(),--需填充的字符串@charvarchar(4),--填充使用的字符@lenint--填充后的长度select@sql='abc'select@c

标签: sqlserver查询语句大全讲解

本文链接地址:https://www.jiuchutong.com/biancheng/348537.html 转载请保留说明!

上一篇:Sql Server查询性能优化之不可小觑的书签查找介绍(sql server如何查询)

下一篇:SqlServer参数化查询之where in和like实现详解(sql参数化是什么意思)

  • 换了公司后个税还要申请申报吗
  • 银行存款属于其他货币资金核算内容吗
  • 企业所得税汇算清缴操作流程
  • 出租车定额发票真伪查询
  • 金税盘电子发票怎么读入
  • 公司承担社保能放到生产成本里吗
  • 增值税电子发票能抵税吗
  • 辅助材料属于成本吗
  • 缴纳个税和社保
  • 房地产结转收入是什么意思
  • 固定资产常用计算公式
  • 模具可以申请专利吗
  • 一个公司只有一个财务人员,可以吗
  • 合同印花税怎么交
  • 文化事业建设费的征收范围
  • 产假期间工资如何发放
  • 开给学校的发票要税号吗
  • 深圳制造业税收
  • 2019水利基金税率是多少
  • 停车管理费收费依据
  • 出口退税收入凭证怎么填
  • 普通发票年份代码有什么具体含义?
  • 半年报利润分配是否需要审计?
  • 什么科目呀
  • 计提其他应收款坏账
  • 防暑降温用品进什么科目
  • 企业所得税税率2.5% 5% 25%
  • win7原版系统安装后没有任何驱动
  • 电子发票上的电子税章如何才能自动生成
  • 自用房地产转换为采用公允价值
  • 鸿蒙系统怎么隐藏状态栏
  • 正版的win10多少钱
  • 共用水电无法取水怎么办
  • PHP:pg_meta_data()的用法_PostgreSQL函数
  • 民办非企业的税金及附加放在哪个科目
  • 税前扣除凭证管理办法第九条称小额零星支出是
  • 华盛顿州帕卢斯心雕塑
  • vue ts
  • php读取文件
  • 将预收款冲抵前欠货款会计分录
  • 性能优化有什么用
  • 计提租金怎么做会计分录
  • python中函数的用法
  • 2022年最新公务接待用餐标准
  • 企业对外担保能收担保费吗
  • php call方法
  • 出纳人员收取现金合法吗
  • 建筑业差额纳税申报
  • 发票含税和不含税的区别
  • 制造费用属于哪一类会计科目
  • 建筑业服务包含哪些?
  • 退伍军人9000补助
  • 企业所得税的减免税额
  • 活动费用在哪个科目
  • 企业买期货账务处理
  • 管家婆记账可以都有凭证做吗?
  • 在建工程转长期待摊费用是什么意思
  • 结转已销商品的销售成本分录
  • 利润分配审计案例
  • 销项税小于进项税是亏本吗
  • mysql复制命令
  • sql查询当前年份
  • winxp电脑显示器亮度怎么调
  • win7怎么设置桌面位置
  • mac 命令大全
  • 怎么压缩视频
  • ubuntu20.04升级21.04
  • linux中符号连接文件是什么意思
  • win10系统怎么隐藏c盘
  • centos文本编辑器
  • vsftpd教程
  • jquery设置滚动条
  • jquery实现
  • [置顶]津鱼.我爱你
  • nodejs发送post请求socket hand up
  • javascript教程chm
  • 金税盘联网步骤
  • 陕西省国家税务局总局官网
  • 经信委和科技局的区别
  • 慧付钱包app官网下载
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设