读书摘要:
1、Begin Tran
delete from production.ProductCosthistory
该查询返回受影响的记录数。注意该查询故意没有提交,也就是说,其中包含Begin Tran命令,但没有Rollback和Commit命令。由于没有后面的命令,该表当前处于锁定状态。通常,用户可能运行没有begin tran的查询。在这些情况下,实际上它是一个隐式事务,且该事务在批处理完成时立即提交。
接下来,在不关闭前一个窗口的情况下,打开一个新的查询窗口,并在AdventureWorks数据库中运行如下查询。
Select * from Production.ProductCostHistory
该查询永远不会返回结果,且将处于挂起状态。注意在每个查询窗口的地步显示了登录名,并在括号中显示进程ID,在保持查询窗口打开的同时打开“活动监视器”,查看这些链接当前的状态。
用户可通过添加With (nolock)字句,请求对未提交数据的脏读。
select * from production.ProductCosthistory
with (nolock)
2、在T-SQL中监视进程
sp_who和sp_who2与“活动监视器”非常类似。
3、sys.dm_exec_connections
4、DBCC INPUTBUFFER
让用户能够查看各个进程ID在运行哪些SQL命令。该命令只接受一个输入参数,即要对其进行诊断的连接的进程ID。
5、Sys.dm_exec_sql_text
有些时候可能需要表格格式的DBCC INPUTBUFFER结果。可使用动态管理函数sys.dm_exec_sql_text来获得特定查询的文本。他可以与sqy.dm_exec_query_stats动态管理视图结合使用,以获得所有数据库中性能最差的查询。
在设计select语句时,应该注意以下几种影响查询效率的情况。
(1)没有创建索引,或者没有正确地使用索引。这是最有可能影响数据库查询的原因之一。创建索引是优化数据查询效率的重要手段。
(2)存在死锁的情况,从而导致select语句挂起,无法返回结果集。
(3)返回了不必要的列。很多程序员喜欢使用select * fromtablename 来查询表或视图中的数据,*代表或视图中的所有字段。如果表或视图的数据里比较大,则查询所有字段会浪费更多的系统资源,从而影响查询效率。建议用户在使用select语句时,只返回必要的列。
(4)在SELECT语句中使用WHERE子句,设置查询条件,只返回必要的记录。
(5)使用在SELECT语句中使用TOP关键字,限制返回的记录数量。
(6)如果在WHERE子旬中使用LIKE谓词进行模糊查询,则要注意通配符的使用方法。
(7)慎用UNION关键字,因为它会影响查询的效率。
(8)慎用DISTINCT关键字,因为在结果集中返回重复的记录并不会影响查询的效率。相反,过滤掉重复的记录会浪费查询的时间和系统资源。因此,除非必须如此,不要使用DISTINCT关键字。
(9)如果需要经常对表中的数据进行统计,可以在表中增加一个统计字段,每次表中数据发生变化时,动态更新统计字段。这样,在查询统计结果时,就不需要临时对表中的数据统计计算了。
(10)如果需要多次对一个数据量非常大的表中的一部分数据进行查询操作,可以将这部分数据保存到临时表中,然后对临时表进行查询操作。如果需要,可以在临时表上创建索引。
(11)在WHERE子旬中,有时使用BETWEEN关键字比使用IN关键字要快,因为IN关键字对其后面的集合中的每个元素都进行比较操作。如果必须使用IN关键宇,则可将频繁使用的值放在集合的前面,从而减少比较的次数。
(12)尽量少使用视图,特别是嵌套视图,可以直接从表中获取数据。在开发应用程序时,有时程序员为了方便,设计一个包含很多字段的大视图,无论需要什么数据,都可以通过查询此视图获取到。实际上,最好从表中直接获取数据,以避免查询大视图而造成的系统开销。建议使用存储过程代替视图,从而提高执行的效率。
(13)如果不需要对结果集进行排序,则不使用ORDERBY子句,因为排序操作会占用系统资源。
(14)不要在WHERE子句中“=”的左侧使用函数和表达式,因为系统将无法应用函数或表达式中的索引。
(15)当判断表中是否包含记录时,使用EXISTS关键字,而不要使用COUNT统计表中所有的记录数量。
Physical Disk包含的主要计数器
计数器 | 说明 |
%Disk Read Time | 所选磁盘驱动器为读请求提供服务所用时间的百分比 |
%Disk Time | 所选磁盘驱动器为读或写入请求提供服务所用时间的百分比 |
%Disk Write Time | 所选磁盘驱动器为写请求提供服务所用时间的百分比 |
%Idle Time | 在实例间隔时磁盘闲置时间的百分比 |
Avg.Disk Bytes/Read | 在读取操作时从磁盘上传送的字节平均数 |
Avg.Disk Bytes/Transfer | 在写入或读取操作时从磁盘上传送或传出字节的平均数 |
Avg.Disk Bytes/Write | 在写入操作时从磁盘上传送的字节平均数 |
Avg.Disk Queue Length | 读取和写入请求的平均数 |
Avg.Disk Read Queue Length | 读取请求的平均数 |
Avg.Disk sec/Read | 以秒计算的在磁盘上读取数据的所需平均时间 |
Avg.Disk sec/Tranfer | 以秒计算的在磁盘传送所需平均时间 |
Avg.Disk sec/Write | 以秒计算的在此盘上写入数据的所需平均时间 |
Avg.Disk Write Queue Length | 写入请求的平均数 |
Current Disk Queue Length | 在收集性能数据时磁盘上当前的请求数量。为了提高性能,此差应该平均小于2 |
Disk Bytes/sec | 在进行写入或读取操作时从磁盘上传送或传出的字节速率 |
Disk Read Bytes/sec | 在读取操作时从磁盘上传字节的速率 |
Disk Read/sec | 在此盘上读取操作的速率 |
Disk Transfer/sec | 在磁盘上读取/写入操作速率 |
Disk Write Bytes/sec | 在写入操作时传送到磁盘上的字节速度 |
Disk Writes/sec | 在磁盘上写入操作的速率 |
可以使用Current Disk Queue length 和 %Disk Time计数器的值检测磁盘子系统中的瓶颈。如果这两个计数器的值一直很高,则可以考虑更换速度更快的磁盘或将数据库文件移动到其他物理硬盘上。
计数器 | 说明 |
Buffer cache hit ratio | 可在缓冲池中找到儿不必要从磁盘读取的页所占的百分比 |
checkpoint pages/sec | 检查点或其他要求刷新全部脏页的操作所刷新的页数 |
databse pages | 缓冲池中有数据库内容的页数 |
Free list stalls/sec | 必须等待可用页的请求数 |
Free pages | 所有可用列表的总页数 |
Lazy writes/sec | 缓冲区管理器的惰性编写器写入的缓冲区数 |
Page life expectancy | 没有引用的页停留在缓冲池中的时间(秒) |
Page lookups/sec | 要求在缓冲池中查找页的请求数 |
Page reads/sec | 执行的物理数据库页读取数 |
Page reads/sec | 执行的物理数据库页写入数 |
Page writes/sec | 缓冲池中的理想的页数 |
Total pages | 缓冲池中的页数,包括数据库页,可用页和被盗页 |
通常可以监测Page reads/sec和Page writes/sec这两个计数器,如果它们的值比较高,则需要调整应用程序或数据库以较少I/O操作。增加硬件的I/O容量或添加内存
SQL Server设置的情况下,SQL server中的性能杀手按照粗略的顺序(最糟糕的首先出现)排列如下:
1、低质量的索引
2、不精确的统计
3、过多的阻塞和死锁
4、不基于数据集的操作,通常是T-sql游标;
5、低质量的查询设计
6、低质量的数据库设计
7、过多的碎片
8、不可重用的执行计划
9、低质量的执行计划,通常是因为参数嗅探(parameter sniffing)所导致的
10、执行计划频繁重编译
11、游标的错误使用
12、数据库日志的错误配置
13、过多使用或者错误配置tempdb