sql server sql性能快速定位

简介

对于写出实现功能的SQL语句和既能实现功能又能保证性能的SQL语句的差别是巨大的。很多时候开发人员仅仅是把精力放在实现所需的功能上,而忽略了其所写代码的性能和对SQL Server实例所产生的影响(也就是IO,CPU,内存方面的消耗).这甚至有可能使整个SQL Server实例跪了。本文旨在提供一些简单的步骤来帮助你优化SQL语句。

市面上已经有很多关于如何优化SQL Server性能的书籍和白皮书。所以本文并不打算达到那种深度和广度,而仅仅是为开发人员提供一个快速检测的列表来找到SQL语句中导致瓶颈产生的部分。

在开始解决性能问题之前,合适的诊断工具是必须的。除去众所周知的SSMS和SQL Profiler,SQL Server 2008还带有众多DMV来提供关键信息。本篇文章中,我将使用SSMS和一些DMV来找到SQL的瓶颈

那么,我们从哪开始

我的第一步是查看执行计划。这一步既可以通过SMSS也可以通过SQL Profiler实现,为了简便起见,我将在SMSS中获取执行计划。

1) 检查你是否忽略掉了某些表的连接的条件,从而导致了笛卡尔积(Cross)连接(Join)。比如,在生产系统中有两个表,每个表中有1000行数据。这其中绝大多数数据并不需要返回,如果你在这两个表上应用了Cross Join,返回的结果将会是100万行的结果集!返回如此数量的数据包括将所有数据从物理存储介质中读取出来,因而占用了IO。然后这些数据将会被导入内存,也就是SQL Server的缓冲区。这会将缓冲区内的其它页Flush出去。

2)查看你是否忽略了某些Where子句,缺少Where子句会导致返回额外不需要的行。这产生的影响和步骤一所产生的影响是一样的。

3)查看统计信息是否是自动创建和自动更新的,你可以在数据库的属性里看到这些选项

在默认条件下创建一个新数据库,Auto Create Statistics和Auto Update Statistics选项是开启的,统计信息是用于帮助查询优化器生成最佳执行计划的。这份白皮书对于解释统计信息的重要性以及对于执行计划的作用解释的非常到位。上面那些设置可以通过右键数据库,选择属性,在“选项”中找到。

4)检查统计信息是否已经过期,虽然统计信息是自动创建的,但是更新统计信息从而反映出数据的变化也同样重要。在一个大表中,有时候虽然Auto Update Statistics 选项已经开始,但统计信息依然无法反映出数据的分布情况。默认情况下,统计信息的更新是基于抽取表中的随机信息作为样本产生的。如果数据是按顺序存储的,那么很有可能数据样本并没有反映出表中的数据情况。因此,推荐在频繁更新的表中,统计信息使用Full Scan选项来定期更新。这种更新可以放到数据库闲时来做。

DBCC SHOW_STATISTICS命令可以用于查看上次统计信息的更新时间,行数以及样本行数.在这个例子中,我们可以看到Person.Address表上的AK_Address_rowguid索引的有关信息:

USE AdventureWorks;
GO
DBCC SHOW_STATISTICS ("Person.Address", AK_Address_rowguid);
GO

下面是输出结果,请注意Updated,Rows,Rows Sampled这三个列

如果你认为统计信息已经过期,则可以使用sp_updatestats这个存储过程来更新当前数据库中的所有统计信息:

或者使用FULLSCAN选项,则关于表Person.Address上的所有统计信息将会被更新:

UPDATE STATISTICS Person.Address WITH FULLSCAN

5)查看执行计划是否出现任何表或者索引的扫描(译者注:不是查找),在大多数情况下(这里假设统计信息是最新的),这意味着索引的缺失。下面几个DMV对于查找缺失索引很有帮助:

i) sys.dm_db_missing_index_details

ii) sys.dm_db_missing_index_group_stats

iii) sys.dm_db_missing_index_groups

接下来的几个语句使用了上面的DMV,按照索引缺失对于性能的影响,展现出信息:

SELECT avg_total_user_cost,avg_user_impact,user_seeks, user_scans,
ID.equality_columns,ID.inequality_columns,ID.included_columns,ID.statement
FROM sys.dm_db_missing_index_group_stats GS
LEFT OUTER JOIN sys.dm_db_missing_index_groups IG On (IG.index_group_handle = GS.group_handle)
LEFT OUTER JOIN sys.dm_db_missing_index_details ID On (ID.index_handle = IG.index_handle)
ORDER BY avg_total_user_cost * avg_user_impact * (user_seeks + user_scans)DESC

你也可以使用数据引擎优化顾问来找出缺失的索引以及需要创建哪些索引来提高性能。

6)查看是否有书签查找,同样,在执行计划中找到书签查找十分容易,书签查找并不能完全避免,但是使用覆盖索引可以大大减少书签查找。

7)查看排序操作,如果在执行计划中排序操作占去了很大一部分百分比,我会考虑以下几种方案:

  • 按照所排序的列创建聚集索引,但这种方式一直存在争议。因为最佳实践是使用唯一列或者Int类型的列作为主键,然后让SQL Server在主键上创建聚集索引。但是在特定情况下使用排序列创建聚集索引也是可以的
  • 创建一个索引视图,在索引视图上按照排序列创建聚集索引
  • 创建一个排序列的非聚集索引,把其他需要返回的列INCLUDE进去

在我的另一篇文章中,我将会详细阐述选择最佳方案的方法。

8)查看加在表上的锁,如果所查的表由于一个DML语句导致上锁,则查询引擎需要花一些时间等待锁的释放。下面是一些解决锁问题的方法:

  • 让事务尽可能的短
  • 查看数据库隔离等级,降低隔离等级以增加并发
  • 在Select语句中使用表提示,比如READUNCOMMITTED 或 READPAST.虽然这两个表提示都会增加并发,但是ReadUnCommited可能会带来脏读的问题,而READPAST会只返回部分结果集

9)查看是否有索引碎片,索引碎片可以使用sys.dm_db_index_physical_statsDMV轻松查看,如果索引碎片已经大于30%,则推荐索引重建.而索引碎片小于30%时,推荐使用索引整理。索引碎片因为使查询需要读取更多的列从而增加了IO,而更多的页意味着占用更多的缓冲区,因此还会形成内存压力。

如下语句根据索引碎片的百分比查看所有索引:

Declare @db	SysName;
Set @db = '<DB NAME>'; SELECT CAST(OBJECT_NAME(S.Object_ID, DB_ID(@db)) AS VARCHAR(20)) AS 'Table Name',
CAST(index_type_desc AS VARCHAR(20)) AS 'Index Type',
I.Name As 'Index Name',
avg_fragmentation_in_percent As 'Avg % Fragmentation',
record_count As 'RecordCount',
page_count As 'Pages Allocated',
avg_page_space_used_in_percent As 'Avg % Page Space Used'
FROM sys.dm_db_index_physical_stats (DB_ID(@db),NULL,NULL,NULL,'DETAILED' ) S
LEFT OUTER JOIN sys.indexes I On (I.Object_ID = S.Object_ID and I.Index_ID = S.Index_ID)
AND S.INDEX_ID > 0
ORDER BY avg_fragmentation_in_percent DESC

下面语句可以重建指定表的所有索引:

ALTER INDEX ALL ON <Table Name> REBUILD;

下面语句可以重建指定索引:

ALTER INDEX <Index Name> ON <Table Name> REBUILD;

当然,我们也可以整理索引,下面语句整理指定表上的所有索引:

ALTER INDEX ALL ON <Table Name> REORGANIZE;

下面语句指定特定的索引进行整理:

ALTER INDEX <Index Name> ON <Table Name> REORGANIZE;

在重建或整理完索引之后,重新运行上面的语句来查看索引碎片的情况。

总结

上面的9个步骤并不是优化一个SQL语句必须的,尽管如此,你还是需要尽快找到是哪个步骤导致查询性能的瓶颈从而解决性能问题。就像文中开篇所说,性能的问题往往是由于更深层次的原因,比如CPU或内存压力,IO的瓶颈(这个列表会很长….),因此,更多的研究和阅读是解决性能问题所必须的。

----------------------------------------

原文链接:http://www.sqlservercentral.com/articles/Performance+Tuning/70647/

sql优化 性能快速定位的更多相关文章

  1. 快速定位隐蔽的sql性能问题及调优【转载】

    在前几天,有个开发同事问我一个问题,其实也算是技术救援,他说在有个job数据处理的频率比较高,在测试环境中很难定位出在哪有问题,而且速度也还能接 受,但是在生产环境中总是会慢一些,希望我能在测试环境中 ...

  2. SQL Server 性能优化之RML Utilities:快速入门(Quick Start)(1)

      SQL Server 性能优化之RML Utilities:快速入门(Quick Start)(1) 安装Quick Start工具 RML(Replay Markup Language)是MS ...

  3. SQL性能优化:如何定位网络性能问题

    一同事跟我反馈他遇到了一个SQL性能问题,他说全表只有69条记录,客户端执行耗费了两分多钟,这不科学呀.要我分析一下原因并解决.我按照类似表结构,构造了一个案例,测试截图如下所示 这个表有13800K ...

  4. Linux性能优化从入门到实战:06 CPU篇:快速定位CPU瓶颈

    CPU性能指标      (1)CPU使用率:1) 用户态CPU使用率(包括用户态 user 和低优先级用户态 nice).2) 系统CPU使用率.3) 等待 I/O 的CPU使用率.4) 软中断和硬 ...

  5. Sql Server 性能优化之包含列

    导读:数据数优化查询一直是个比较热门的话题,小生在这方面也只能算是个入门生.今 天我们就讲下数据库包含列这个一项的作用及带来的优化效果 引用下MSDN里面的一段解释: 当查询中的所有列都作为键列或非键 ...

  6. SQL Server 性能优化之——系统化方法提高性能

    SQL Server 性能优化之——系统化方法提高性能 阅读导航 1. 概述 2. 规范逻辑数据库设计 3. 使用高效索引设计 4. 使用高效的查询设计 5. 使用技术分析低性能 6. 总结 1. 概 ...

  7. 性能优化之永恒之道(实时sql优化vs业务字段冗余vs离线计算)

    在项目中,随着时间的推移,数据量越来越大,程序的某些功能性能也可能会随之下降,那么此时我们不得不需要对之前的功能进行性能优化.如果优化方案不得当,或者说不优雅,那可能将对整个系统产生不可逆的严重影响. ...

  8. 如何利用快照( snapshot )功能快速定位性能问题

    我们常常会遇到这样的困惑,收到用户或者客服的反馈,平台使用有问题,但是测试人员搭建环境后又没办法复现故障,最后导致问题没法解决,眼睁睁地看着用户流失. 这是因为线上生产环境非常复杂.很多时候是偶发性  ...

  9. 使用阿里云RDS for SQL Server性能洞察优化数据库负载-初识性能洞察

    简介 数据库性能调优通常需要较高数据库水平,并伴随较多的前期准备工作,比如收集各种性能基线.不同种类的性能指标.慢SQL日志等,这通常费时费力且效果一般,当面对多个数据库时总体拥有成本会大幅增加.今天 ...

随机推荐

  1. Python闭包装饰器笔记

    Python三大器有迭代器,生成器,装饰器,这三个中使用最多,最重要的就是装饰器.本篇将重要从函数嵌套开始讲起,从而引入闭包,装饰器的各种用法等. python中的一切都是一个对象(函数也是) 1.首 ...

  2. 51开发环境的搭建--KeilC51的安装及工程的创建

    学习单片机的开发,单靠书本的知识是远远不够的,必须实际操作编程才能领会书中的知识点,起到融会贯通的效果.51单片机作为入门级的单片机--上手容易.网上资源丰富.单片机稳定性及资源比较丰富.通过串口即可 ...

  3. 云计算设计模式(二十一)——Sharding分片模式

    云计算设计模式(二十一)——Sharding分片模式 将一个数据存储到一组水平分区或碎片.存储和访问大量数据时,这个模式可以提高可扩展性. 背景和问题 由一个单一的服务器托管的数据存储区可能会受到以下 ...

  4. 原生js--文档加载时间

    onload触发时机:文档和所有的图片都加载完毕 DOMContentLoaded触发时机:文档加载并解析完毕,所有deferred脚本执行完毕.但此时图片和async脚本可能依旧在加载. ready ...

  5. Python pyQt4/PyQt5 学习笔记3(绝对对位,盒布局,网格布局)

    本节研究布局管理的内容. (一)绝对对位  import sys from PyQt4 import QtGui class Example(QtGui.QWidget): def __init__( ...

  6. Android JNI与多线程

    Java通过JNI调用本地C++代码是在同一个线程中的同步调用. JNI中如果新建的线程调用java的代码,那么java代码是运行在JNI线程中的:但是,如果调用UI相关的代码时需要与java主线程通 ...

  7. Android 本地搭建Tomcat服务器供真机测试

    准备工具:tomcat    环境:win7 + JDK1.8 + tomcat 9.0.13(64bit) 准备工具:tomcat    1.tomcat官网下载   https://tomcat. ...

  8. Android studio 怎么使用已经下载好的Android SDK ?

    AS:3.1.2 ---> android-studio-ide-173.4720617-windows32.zip sdK: gradle:4.4 1. 2. 3. 4. 5. 下面重要一步, ...

  9. [BeiJing2011]元素[贪心+线性基]

    2460: [BeiJing2011]元素 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1245  Solved: 652[Submit][Stat ...

  10. 【BZOJ1004】[HNOI2008]Cards Burnside引理

    [BZOJ1004][HNOI2008]Cards 题意:把$n$张牌染成$a,b,c$,3种颜色.其中颜色为$a,b,c$的牌的数量分别为$sa,sb,sc$.并且给出$m$个置换,保证这$m$个置 ...