SQL性能杀手
在已经优化了硬件、操作系统和SQL配置的情况下,SQL中的性能杀手:
·低质量的索引
·不精确的统计
·过多的阻塞和死锁
·低质量的查询设计
·低质量的数据库设计
·过多的碎片
·不可重用的执行
·低质量的执行计划
·执行计划频繁重编译
·游标的错误使用
·数据库日志的错误配置
·过多使用或者错误配置tempdb
低质量的索引
对于一个缺乏正确索引的查询,SQL必须在执行查询时读取和处理多得多的数据,这导致磁盘、内存和CPU上有很大的压力,显著的增加查询执行时间。增加查询执行时间导致过多的阻塞和死锁。
不精确的统计
SQL服务器非常依赖基于开销的优化,所以精确的数据分布统计对于有效的索引使用极端重要。没有精准的统计,SQL内建的查询优化器就不能精确的估计查询影响的行数。
性能监测工具
运行perfmon
查询每秒登录的时间
Select cntr_value
From sys.dm_os_performance_counters
Where OBJECT_NAM = ‘’//服务器名称
And counter_name = ‘logins/sec’//每秒登录多少次
识别发生在系统中的等待,查询当前最长的等待
Select top 10 * from sys.dm_os_wait_stats
Order by wait_time_ms desc
当SQL耗尽了缓冲或内存时,SQL中的一个进程(lazy writer)必须不段的工作,这将消费额外的CPU周期并且执行附加的物理磁盘I/O将内存页面写回磁盘
通过下面语句管理最小最大内存配置。
Exec sp_configure ‘min server memory(MB)’
Exec sp_configure ‘max server memory(MB)’
注意:服务器最小内存默认值为0,最大为2147483647,服务器最大内存不能设置为小于4MB。
查询设计分析
·查询设计影响性能的方面
·查询设计有效使用索引的方法
·优化器提示在查询性能上的作用
·数据库约束在查询性能上的作用
·资源密集度较低的查询设计
·有效使用过程缓冲的查询设计
·减少网络开销的查询设计
·减少查询事务开销的技术
一般记住以下建议能确保最佳性能:
·在小的结果集上操作
·有效使用索引
·避免优化器提示
·使用域和参照完整性
·避免资源密集型的查询
·减少网络传输数量
·减少事务开销
在小的结果集上操作
应该限制操作的数据量,包括列数和行数。遵循原则:
·限制选择列表中的列数
·使用高选择性的WHERE子句来限制返回的行数
限制选择列表中的列数
不要使用输出结果不需要的列。例如select *,错误
Select [Name],TerritoryID from SalesTerritory as st
Where st.[Name] = ‘australia’
在NAME列上的覆盖索引使通过索引本身的查询很快,而不需要访问聚集索引。当开启STATISTICS IO和STATISTICS TIME开关,将得到以下逻辑读取数量和执行时间
Table ‘SalesTerritory’.Scan count 0, logical reads 2,CPU time = 0ms,elapsed time = 17ms
使用高选择性的WHERE子句
在WHERE子句中引用的列的选择性控制着列上索引的使用。
11.3有效的使用索引
索引使用的查询设计原则:
·避免不可参数化的搜索
·避免在WHERE子句列上使用算数运算符
·避免WHERE子句列上的函数
11.3.1避免不可参数化的搜索
11.3.2避免WHERE子句列上的算术运算符
如:
SELECT * FROM TABLE AS POH
WHERE POH.ID * 2 = 3400
改为
SELECT * FROM TABLE AS POH
WHERE POH.ID = 3400/2
11.3.3避免WHERE子句列上的函数
如:
SELECT D.NAME FROM TABLE AS D WHERE SUBSTRING(D.[NAME],1,1) = ‘F’
改为:
SELECT D.NAME FROM TABLE AS D WHERE D.[NAME] LIKE ‘F%’
11.4避免优化器提示
11.5使用域和参照完整性
11.5.1非空约束
非空约束用于定义特定列中不能输入NULL值从而实现域完整性。
对比没有NULL和有NULL的执行过程
没有NULL的
有NULL的,仅仅只是在后面增加了,or p.firstname is null
注意:当数据为知时,也许不能设定默认值。这时候又将出现NULL。这是不可避免的,但是要尽可能的减少这样的情况。
当不可避免的要处理NULL值时,可以使用过滤索引来从索引中删除NULL的值,从而改进索引的性能。
11.5.2声明参照完整性
声明参照完整性用于定义父表和子表上的参照完整性。它确保子表中的记录只当父表中存在对应记录时存在。这个原则唯一例外的是,链接子表和附表行的子表标识符可以为NULL值。
11.6避免资源密集型查询
减少查询覆盖的技术有:
·避免数据类型转换
·使用EXISTS代替COUNT(*)来验证数据存在
·使用UNION ALL代替UNION
·为聚合和排序操作使用索引
·避免批查询中的局部变量
·小心命名存储过程
(2013-3-25)